热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Nginx与Tomcat、Client之间请求的长连接配置不

http://bert82503.iteye.com/blog/2152613  





http://bert82503.iteye.com/blog/2152613

 

前些天,线上出现“

服务端长连接与客户端短连接引起Nginx的Writing、Active连接数过高问题

”,这个是由于“服务端使用HTTPs长连接,而客户端使用短连接”引起。这几天,发现Nginx与Tomcat之间也存在同样的问题,原因是两边的相关配置参数不一致引起的。(这是




细活

!)

 

先说说服务为什么使用

HTTPs长连接技术

?有如下几个原因:



  1. 对响应时间要求较高;


  2. 服务走的是公网,客户端与服务端的TCP

    建立的三次握手



    断开的四次握手

    都需要40ms左右(真实数据包计算出来的),共需要

    80ms

    左右;


  3. 每个接入方使用的IP就若干个,需要建立的请求连接有限。


使用长连接技术,可以大幅减少TCP频繁握手的次数,极大提高响应时间;同时,即使使用长连接技术,也不需要消耗很多的系统资源用来缓存sockets会话信息。

 

以下是在自己电脑上验证三者之间的长连接请求,连接存活时间都为

5min


【环境】

操作系统:Ubuntu 14.04 LTS

Nginx:

1.6.2

Tomcat:

7.0.51

JDK:

1.7.0_51

Client:

HttpClient 


4.3.5

 

【相关配置】

1. Nginx - 反向代理


nginx.conf:


http

 {


    ...




    ##

    # 与Client连接的长连接配置

    ##

    # 

http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_requests

    # 设置通过"一个存活长连接"送达的最大请求数(默认是

100

,建议根据客户端在"keepalive"存活时间内的总请求数来设置)

    # 当送达的请求数超过该值后,该连接就会被关闭。(通过设置为5,验证确实是这样)

    

keepalive_requests 


8192

;

 

    # 

http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout

    # 第一个参数设置"keep-alive客户端长连接"将在"服务器端"继续打开的超时时间(默认是

75秒

,建议根据具体业务要求来,但必须要求所有客户端连接的"Keep-Alive"头信息与该值设置的相同(这里是5分钟),同时与上游服务器(Tomcat)的设置是一样的)

    # 可选的第二个参数设置“Keep-Alive: timeout=time”响应头字段的值


    keepalive_timeout

 

300s 300s

;

 

    ...

    include /etc/nginx/web_servers.conf;

    include /etc/nginx/proxy_params;

}




web_servers.conf:



upstream

 web_server {


    server 127.0.0.1:8080;




    # 

http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

    # 连接到上游服务器的最大并发空闲keepalive长连接数(默认是

未设置

,建议与Tomcat 

Connector

中的

maxKeepAliveRequests

值一样)

    # 当这个数被超过时,使用"最近最少使用算法(LUR)"来淘汰并关闭连接。

    

keepalive

 

512

;


}





server

 {

    listen 80;

    server_name lihg.com www.lihg.com;

 


    location

 / {

        proxy_pass http://web_server;

 

        ##

        # 与上游服务器(Tomcat)建立keepalive长连接的配置,可参考上面的keepalive链接里的"For HTTP"部分

        ##

        # 

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_http_version

        # 设置代理的HTTP协议版本(默认是1.0版本)

        # 使用keepalive连接的话,建议使用1.1版本。


        proxy_http_version

 

1.1

;

        # 

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header

        # 允许重新定义或追加字段到传递给代理服务器的请求头信息(默认是close)


        proxy_set_header

 

Connection

 

""

;

 

        proxy_redirect off;

    }

}

 

[参考]




  1. nginx反向代理配置keepalive




  2. keepalive for HTTP - Module ngx_http_core_module



 

2. Tomcat



conf/server.xml




   


   

               maxThreads="

512

"


               minSpareThreads="10"


               acceptCount="768"


               


               cOnnectionTimeout="1000"


               maxCOnnections="1280"


               

keepAliveTimeout

="

300000

"


               

maxKeepAliveRequests

="

512

"


               


               enableLookups="false"


               URIEncoding="utf-8"


               redirectPort="8443"


               compression="on" compressiOnMinSize="1024" compressableMimeType="text/html,text/xml,text/Javascript,text/css,text/plain,application/json,application/xml"


               server="webserver" />

 [参考]


The HTTP Connector - Tomcat 7 Configuration Reference

 

3. Client

客户端HTTP "Keep-Alive"实现代码,请打开下一行的链接。


KeepAliveHttpClientsTest

 -> 

httpclient-x

 

【结果验证】

使用 "sudo 

netstat

 -antp | grep 80" 监控与Nginx相关的线程状态

 


netstat命令输出格式

Proto    Recv-Q             Send-Q               Local Address                     Foreign Address                  State              PID/Program name

协议     接收队列长度    发送队列长度     本地socket的地址和端口号  远程socket的地址和端口号  socket状态   进程id/进程名称

 

套接字(socket)状态


ESTABLISHED

:含有一条已建立连接(connection)的socket

SYN_SENT:正在积极尝试建立一条连接的socket

SYN_RECV:接收到来自网络的一个连接请求

FIN_WAIT1:socket已关闭,同时连接正在关闭中

FIN_WAIT2:连接已关闭,同时socket正在等待远程终端的一个关闭请求


TIME_WAIT

:socket正在等待关闭仍然在网络中的处理包

CLOSE:socket未被使用

CLOSE_WAIT:远程终端已经关闭,等待本地socket关闭

LAST_ACK:远程终端已经关闭,同时本地socket也关闭了。等待确认包

LISTEN:socket正在监听传入的连接

CLOSING:两边socket都已关闭,但仍然还没有我们所需要的发送数据

UNKNOWN:未知的socket状态

 

 

=====================


单个请求

的线程状态

=====================

# 第1次请求,nginx分别与上游服务器(tomcat)、client互相建立

1条连接

tcp        0      0 0.0.0.0:

80

              0.0.0.0:*               LISTEN      1010/

nginx

      

tcp        0      0 127.0.0.1:

47272

         127.0.0.1:

8080

          ESTABLISHED 1014/

nginx: worker

 (nginx -> tomcat)

tcp        0      0 127.0.0.1:

80

            127.0.0.1:

53240

         ESTABLISHED 1014/

nginx: worker

 (nginx -> client)

tcp6       0      0 127.0.0.1:

8005

          :::*                    LISTEN      10912/

java

      

tcp6       0      0 :::

8080

                 :::*                    LISTEN      10912/

java

      

tcp6       0      0 127.0.0.1:53240         127.0.0.1:

80

            ESTABLISHED 13845/java      (client -> nginx)

tcp6       0      0 127.0.0.1:

8080

          127.0.0.1:47272         ESTABLISHED 10912/java      (tomcat -> nginx)

 

# 休眠10秒钟后,发起第2次请求

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1010/nginx      

tcp        0      0 127.0.0.1:

47272

         127.0.0.1:8080          ESTABLISHED 1014/nginx: worker 

tcp        0      0 127.0.0.1:80            127.0.0.1:

53240

         ESTABLISHED 1014/nginx: worker 

tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      10912/java      

tcp6       0      0 :::8080                 :::*                    LISTEN      10912/java      

tcp6       0      0 127.0.0.1:53240         127.0.0.1:80            ESTABLISHED 13845/java      

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47272         ESTABLISHED 10912/java      

 



超过keepalive存活时间(5min)后

,nginx已断开与上游服务器(tomcat)的长连接,同时与client连接进入关闭过程

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1010/nginx      

tcp        0      0 127.0.0.1:

80

            127.0.0.1:

53240

         

FIN_WAIT2

   -                (nginx -> client)

tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      10912/java      

tcp6       0      0 :::8080                 :::*                    LISTEN      10912/java      

tcp6       1      0 127.0.0.1:53240         127.0.0.1:

80

            

CLOSE_WAIT

  13845/java      (client -> nginx)

tcp6       0      0 127.0.0.1:

8080

          127.0.0.1:47272         

TIME_WAIT

   -               (tomcat -> nginx)

 

 

# 休眠7分钟后,发起第3次请求。nginx与上游服务器(tomcat)、client

重新建立新的长连接

(

不同的端口号

)

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1010/nginx      

tcp        0      0 127.0.0.1:80            127.0.0.1:

53242

         

ESTABLISHED

 1014/

nginx: worker

 (nginx -> client)

tcp        0      0 127.0.0.1:

47274

         127.0.0.1:8080          

ESTABLISHED

 1014/

nginx: worker

 (nginx -> tomcat)

tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      10912/java      

tcp6       0      0 :::8080                 :::*                    LISTEN      10912/java      

tcp6       0      0 127.0.0.1:53242         127.0.0.1:80            ESTABLISHED 13845/java      (client -> nginx)

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47274         ESTABLISHED 10912/java      (tomcat -> nginx)

 

# 休眠10秒钟后,发起第4次请求

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1010/nginx      

tcp        0      0 127.0.0.1:80            127.0.0.1:53242         ESTABLISHED 1014/nginx: worker 

tcp        0      0 127.0.0.1:47274         127.0.0.1:8080          ESTABLISHED 1014/nginx: worker 

tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      10912/java      

tcp6       0      0 :::8080                 :::*                    LISTEN      10912/java      

tcp6       0      0 127.0.0.1:53242         127.0.0.1:80            ESTABLISHED 13845/java      

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47274         ESTABLISHED 10912/java

 

# 请求刚结束后,nginx断开与client的长连接,但与上游服务器(tomcat)的长连接还打开着,直到超过keepalive存活时间(5min)后才会被关闭。若在keepalive存活时间内再次发起请求,nginx与上游服务器(tomcat)的

长连接会被重用

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1010/nginx      

tcp        0      0 127.0.0.1:

47274

         127.0.0.1:8080          

ESTABLISHED

 1014/nginx: worker (nginx -> tomcat)

tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      10912/java      

tcp6       0      0 :::8080                 :::*                    LISTEN      10912/java      

tcp6       0      0 127.0.0.1:

53242

         127.0.0.1:

80

            

TIME_WAIT

   -               (client -> nginx)

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47274         ESTABLISHED 10912/java      (tomcat -> nginx)

 



请求结束


1分钟后

,client到nginx的

TIME_WAIT

长连接也被释放

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1010/nginx      

tcp        0      0 127.0.0.1:

47274

         127.0.0.1:

8080

          ESTABLISHED 1014/nginx: worker 

tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      10912/java      

tcp6       0      0 :::8080                 :::*                    LISTEN      10912/java      

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47274         ESTABLISHED 10912/java     

 

# 请求结束5分钟后,nginx断开与上游服务器(tomcat)的长连接

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1010/nginx      

tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      10912/java      

tcp6       0      0 :::8080                 :::*                    LISTEN      10912/java      

tcp6       0      0 127.0.0.1:

8080

          127.0.0.1:

47274

         

TIME_WAIT

   -               (tomcat -> nginx)

 

 

========================


3个并发请求

的线程状态

========================

# 第1次请求,nginx分别与上游服务器(tomcat)、client互相建立

3条连接

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1010/nginx      

tcp        0      0 127.0.0.1:

80

            127.0.0.1:

53245

         ESTABLISHED 1014/nginx: worker 

tcp        0      0 127.0.0.1:

47279

         127.0.0.1:

8080

          ESTABLISHED 1014/nginx: worker 

tcp        0      0 127.0.0.1:

80

            127.0.0.1:

53247

         ESTABLISHED 1014/nginx: worker 

tcp        0      0 127.0.0.1:

47281

         127.0.0.1:

8080

          ESTABLISHED 1014/nginx: worker 

tcp        0      0 127.0.0.1:

80

            127.0.0.1:

53246

         ESTABLISHED 1014/nginx: worker 

tcp        0      0 127.0.0.1:

47280

         127.0.0.1:

8080

          ESTABLISHED 1014/nginx: worker 

tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      10912/java      

tcp6       0      0 :::8080                 :::*                    LISTEN      10912/java      

tcp6       0      0 127.0.0.1:53247         127.0.0.1:80            ESTABLISHED 13976/java      

tcp6       0      0 127.0.0.1:53245         127.0.0.1:80            ESTABLISHED 13976/java      

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47281         ESTABLISHED 10912/java      

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47280         ESTABLISHED 10912/java      

tcp6       0      0 127.0.0.1:53246         127.0.0.1:80            ESTABLISHED 13976/java      

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47279         ESTABLISHED 10912/java      

tcp6       0      0 127.0.0.1:8080          127.0.0.1:47274         TIME_WAIT   -               

 

[参考]


netstat(8) - Print network connections, routing tables, interface statistics - Linux manual page

 

至此,长连接验证完毕!

 

 

玩的开心!^_^








  • Nginx与Tomcat的完整配置.tar.gz

     (6.7 KB)


  • 下载次数: 0





  • netstat_中文注释版.pdf

     (742.3 KB)


  • 下载次数: 0



Nginx与Tomcat、Client之间请求的长连接配置不一致问题解决




推荐阅读
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 【重识云原生】第四章云网络4.8.3.2节——Open vSwitch工作原理详解
    2OpenvSwitch架构2.1OVS整体架构ovs-vswitchd:守护程序,实现交换功能,和Linux内核兼容模块一起,实现基于流的交换flow-basedswitchin ... [详细]
  • http:expert.csdn.netExperttopic12651265214.xml?temp.6446344感谢两位帮助.由于分太少,没有在这个帖子中给两位加分.在这里 ... [详细]
  • 今天搭建了redis环境,使用自带的benchmark进行了性能测试选择测试键的范围大小默认情况下面,基准测试使用单一的key。在一个基于内存的数据库里,单一key测试和真实情况下 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • POCOCLibraies属于功能广泛、轻量级别的开源框架库,它拥有媲美Boost库的功能以及较小的体积广泛应用在物联网平台、工业自动化等领域。POCOCLibrai ... [详细]
  • python3+tkinter实践历程(四)——模仿CRT完成基于socket通信与tkinter的TCP串口客户端
    python3tkinter实践历程(四)——基于socket通信与tkinter的TCP串口客户端(仿CRT)文章目录系列文章目录分享背景制作背景最终功能工具截图展示代码详解系列 ... [详细]
  • UML 包图
    什么是包包可直接理解为命名空间,文件夹,是用来组织图形的封装,包图可以用来表述功能组命名空间的组织层次。•在面向对象软件开发的视角中&#x ... [详细]
  • iwanttowriteasimpleAppforme(Android).Forthisitisnecessarythattheservercansenddat ... [详细]
  • Docker 快速入门指引
    本文最早发表于本人博客:Docker快速入门指引Docker是什么?Docker是Docker.Inc公司开源的一个基于LXC技术之上构建的Container容器引擎,基于Go语言 ... [详细]
author-avatar
9527
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有