Nginx与Tomcat性能调优,前后端KeepAlive不同步引发的问题

1,378 阅读4分钟

转自:温故而知新666

在http1.1中可以配置服务器端开启keepalive与客户端保持长连接进行优化,这里不过多解释。

我们在nginx.conf配置

    upstream favtomcat {
       server 192.168.80.112:8080;
       keepalive 20;
    }
keepalive_timeout  65s;
keepalive_requests 100;

keepalive_timeout:65s ##设置nginx开启keepalive,超时时间为65秒,也就是说:如果客户端65秒内没有后续的请求过来,nginx就会断掉这个TCP连接,设置为0表示禁用keepalive。

keepalive_requests :100 ##设置长连接能够处理请求的次数,100表示:一个长连接nginx最多处理100次请求就会关闭。

keepalive : 20 ##这个值必须设置,默认为0. 设置每个worker可以保持长连接空闲时的最大连接数。

这里需要特别解释一下,假设nginx有100个请求需要访问Tomcat,那么会建立100个连接,如果双方都支持keepalive,那么这100个连接都是长连接(可以复用那种的),当请求结束后,nginx会立马销毁 80个(100-20),只剩下20个长连接,这20个长连接在Tomcat的keepAliveTimeout时间到期后由Tomcat方关闭。

Tomcat的 keepAliveTimeout这个值可以设置大一些,性能会很好,比如设置个10分钟,20分钟的。

完事大吉,我们来测试。

192.168.80.110 Nginx

192.168.80.112 Tomcat

192.168.80.1 客户端Chrome浏览器

我们在浏览器疯狂刷新Nginx ,为了让浏览器启动最多的连接,我放了一大推的图片,并且图片URL后面加随机数,防止浏览器缓存。

接下来我们通过命令 netstat -ntp | grep nginx 查看服务器TCP连接的情况,后面加了grep nginx是只看nginx的tcp连接。

可以看到浏览器启动了6个TCP连接来与加载资源,无论我们怎么刷新,连接数都不会变,这就是因为使用了Keeplive,所有的连接可以进行复用(请求多个资源),如果把nginx的keepalive设置为0,每次刷新都会使用新的TCP连接,这里会出现大量TIME-WAIT的连接。

上图可以看到,客户端已经与nginx启动了keepalive,复用TCP连接,起到了很大优化,看起来似乎很完美,但是让我们在tomcat的服务器上看看tcp连接情况。 我们使用命令 netstat -ntp

192.168.80.112 tomcat服务器上的截图,我只截取了一部分,实际出现大量的TIME_WAIT的tcp连接。也就是说 客户端与nginx连接时确实是用了keeplive,但是nginx与tomcat的连接却没有启动keeplive,每一次请求都新建一个tcp,用完一次就关闭没有复用,所以出现了大量的TIME_WAIT的TCP连接,如果流量稍微大一些tomcat服务器会因为tcp资源耗尽而宕机。

问题已经发现了,那么如何去解决这个问题呢~,首选要找出问题出现的原因。

1、为什么nginx与tomcat的连接是短连接而不是keepalive长连接?

下图是nginx官网上的一段话,说需要设置proxy_http_version为1.1 并且 Connection 头需要清空,也就是说nginx与tomcat之间是使用http1.0的短连接模式进行通讯的。

让我们通过抓包工具来分析一下nginx与tomcat到底是不是使用http1.0短连接模式通讯的。

可以看到80.1浏览器请求80.110nginx使用的是http1.1,而nginx请求tomcat使用的是1.0.

我们看192.168.80.1 到 192.168.80.110的包,使用http1.1,并且设置了keepalive头。

我们再来看192.168.80.110 到 192.168.80.112的包,使用的是http1.0 并且connection 设置了close,告诉tomcat 连接只用一次,用完即关。

通过上述分析,我们知道了 nginx代理tomcat默认使用http1.0短连接模式,挺坑啊,为什么不直接使用1.1呢。

接下来我们把配置文件加上,在看看效果,记得重启nginx,可以看到通讯已经使用了http1.1 的keeplive模式了。

我们在重新测试疯狂刷新我们的页面,每个几秒刷新1次,刷新5次试试看。

我们在nginx上查看tcp连接情况,一共12个tcp连接,其中6个是客户端与nginx的,另外6个是nginx与tomcat的。

我们在tomcat上查看tcp的连接情况。可以看到一共6个与nginx的tcp连接。这样我们nginx与tomcat也是keepalive长连接了。

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

通过shell统计tcp各种状态的数量