我是如何确认线上CLOSE_WAIT产生的原因及如何解决的。

dukuan 2021-08-30 原文


我是如何确认线上CLOSE_WAIT产生的原因及如何解决的。


1、阐述

  内部架构:Tomcat应用程序—> nginx —> 其他Tomcat应用程序,内部Tomcat应用通过nginx调用其他应用。

  HTTP插件:HttpClient 4.2.3

  关闭连接的代码:httpClient.getConnectionManager().closeIdleConnections(5, TimeUnit.SECONDS);

2、说明

  要说明的是CLOSE_WAIT产生的原因和服务器、nginx、其他配置无关,是HttpClient的getConnectionManager引起的。

3、排查思路

  这个问题已经困扰我很久了,查看过网上的很多办法,也试过很多方法。

  比如:修改服务器内核、修改nginx配置文件、更改nginx版本,都是没有用的,还是上面那句话和服务器、nginx无关。

  最后决定自己分析请求,查找真正的根本原因,以下为排查的最终步骤

4、问题排查

  首先确认CLOSE_WAIT产生的链接,链接的IP和端口

  

  由上图看出是本机链接nginx 81端口造成的CLOSE_WAIT

  抓包分析其中一个CLOSE_WAIT所用的本机端口:

  抓包分析正常关闭的请求:

  分析不正常端口41584,晚上22点01分02秒请求连接,22点01分02秒传输数据结束,22点02分07秒,nginx发送关闭连接的包,Tomcat同意关闭,问题就出现在这里,在Nginx请求关闭连接后,Tomcat并没有回复同样关闭连接的包,没有完成四次握手,故产生了CLOSE_WAIT。

  分析所有正常连接发现没有产生CLOSE_WAIT的端口都是Tomcat主动关闭的,产生CLOSE_WAIT的都是nginx主动关闭,Tomcat被动关闭的。

  再次分析所有的不正常端口

  发现Tomcat周期性的向Nginx发送关闭连接的请求,但是Nginx回复Reset包,说白了就是Tomcat请求关闭连接,但是Nginx说我没有这个链接(已经在前面主动关闭),所有CLOSE_WAIT会一直存在,直至两个小时以后系统强制关闭。至于为什么会周期性的一起并发的关闭的连接,而不是一个一个关闭,或者为什么在收到Nginx关闭连接请求,Tomcat不关闭,看上述Java代码:httpClient.getConnectionManager().closeIdleConnections(5, TimeUnit.SECONDS);

  这段代码表示调用httpClient的getConnectionManager,然后利用closeIdleConnections进行关闭空闲连接,5代表是五秒(不知道解释的对不对)。

  网上查找getConnectionManager,说是httpclient的链接池管理工具。就是把请求都扔里面,然后Manager帮你做相关处理。

  但是上述代码写的是5秒之内连接空闲就会关闭,httpclient又是一个很成熟的技术,于是没有怀疑这个的问题(我不是开发,代码层我无法分析)。

  继续分析其他正常关闭的包,发现并不是所有正常关闭的连接都是五秒关闭的,而产生CLOSE_WAIT的,一般请求关闭都是超过65秒的(65是nginx keepalive timeout的值),为了确认问题的根源,我把nginx的keepalive timeout设置为240秒(Nginx主动关闭连接后,最长Tomcat第一次发送关闭连接的包据数据传输完毕的时间间隔为3分28秒),实时查看CLOSE的增长变得缓慢,改为360秒,几乎不怎么增长,但是还有增长,索性改为0,过了一个多小时,只会下降,不会增多,所以断定是HTTPCLIENT出现的问题。

5、继续分析

  查看httpclient官方文档:http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ClientConnectionManager.html

  上面说在给定的时间内(上述代码的五秒)链接没有被使用,就会在池中关闭连接。同时也会关闭过期的连接。

  看解释说只要连接5秒没有被使用,就会关闭连接,不会大于65秒的,至此又回到诧异懵逼中。。。

  再次回想连接池中周期性发送FIN包,让我判断没有在五秒内关闭连接只有两种可能:一、配置没有生效,二、HTTPCLIENT空闲连接检测机制。

  首先从服务器端快速解决:修改linux内核net.ipv4.tcp_tw_recycle 和 net.ipv4.tcp_timestamps 为 0,sysctl -p使之生效。

  然后把自己的想法说给开发人员说后,无法断定空间连接检测的机制是什么,于是决定修改代码,换用另一种关闭的方式(没有时间考虑上面的两个想法):将所有完成请求的连接通过httpclient的releaseConnection和SHUTDOWN进行关闭,修改完成并在测试环境部署(测试环境也同样有CLOSE_WAIT),运行至今改过代码的并无产生任何CLOSE_WAIT。

 

6、总结

  CLOSE_WAIT产生的原因是由代码引起的,目前能确认的是HTTPCLIENT的getConnectionManager的连接池引起的,但是为什么设置的5秒没有生效,空闲连接的检测机制是什么,这些还无法得知。

  截止到2018年6月4日,自从改了代码和内核参数以后,运行半年,在没有出现过过多CLOSE_WAIT的情况。

  

  

  

  

发表于
2018-01-02 19:23 
杜先生的博客 
阅读(17580
评论(2
编辑 
收藏 
举报

 

版权声明:本文为dukuan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/dukuan/p/8178728.html

我是如何确认线上CLOSE_WAIT产生的原因及如何解决的。的更多相关文章

随机推荐

  1. 【cypress】2. 安装Cypress(windows系统),以及cypress open报错解决。

    安装cypress。 一、操作系统 先确认下你的系统,是否在cypress支持范围之内: macOS 10.9 […]...

  2. 小技巧:如何快速开启一个静态 HTTP 服务?

    静态 HTTP 服务的几个用途: 静态网页的 HTTP 服务,以访问浏览 如:生成的文档、博客等 公开文件的 […]...

  3. 轻装上阵Flink–在IDEA上开发基于Flink的实时数据流程序

    在IDEA上开发基于Flink的实时数据流程序 前言       本文介绍如何在IDEA上快速开发基于Flin […]...

  4. js原生代码实现轮播图案例

    一、轮播图是现在网站网页上最常见的效果之一,对于轮播图的功能,要求不同,效果也不同! 我们见过很多通过不同的方 […]...

  5. jmeter之正则表达式提取器应用

    说到Jmeter正则表达式提取器的应用,就不得不说到关联。所谓关联,就是把应用中动态变化返回的数据获取到,把它 […]...

  6. 从微信小程序开发者工具源码看实现原理(二)- – 小程序技术实现

    wxml与wxss的转换 1、wxml使用wcc转换 2、wxss使用wcsc转换 开发者工具主入口 视图层页 […]...

  7. C++雾中风景番外篇3:GDB与Valgrind ,调试代码内存的工具

    写 C++的同学想必有太多和内存打交道的血泪经验了,常常被 C++的内存问题搅的焦头烂额。(写 core 的经 […]...

  8. 本科生怎样发表自己的论文

      1、论文题目:要求准确、简练、醒目、新颖。       2、目录:目录是论文中主要段落的简表。(短篇论文不 […]...

展开目录

目录导航