我是如何确认线上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空闲连接检测机制。
把自己的想法说给开发人员说后,决定修改代码,换用另一种关闭的方式(没有时间考虑上面的两个想法):将所有完成请求通过httpclient的releaseConnection和SHUTDOWN进行关闭,修改完成并在测试环境部署(测试环境也同样有CLOSE_WAIT),运行至今并无产生任何CLOSE_WAIT。
6、总结
CLOSE_WAIT产生的原因是由代码引起的,目前能确认的是HTTPCLIENT的getConnectionManager的连接池引起的,但是为什么设置的5秒没有生效,空闲连接的检测机制是什么,这些还无法得知。
我是如何确认线上CLOSE_WAIT产生的原因及如何解决的。的更多相关文章
- 一次线上http接口调用不通相关的解决过程
2016-05-25 08:58:34 昨天线上小白系统因为调用外部http接口,超时不释放,导致页面反应很慢,时间一长,报502错误. 上网查了下,502错误是因为服务对于客户的请求没有得到及时的反 ...
- 线上Redis偶发性链接失败排查记
问题过程 输入法业务于12月12日上线了词库接受业务,对部分用户根据用户uuid判断进行回传,在12月17日早上8点多开始出现大量的php报错(Redis went away),报错导致了大量的链接积 ...
- 线上bug分析
昨天下午大神把组内几十号人召集在一起开Online bug分析大会,主要是针对近期线上事故从事故原因和解决方案两个维度来分析. 对金融软件来说,每一次的线上事故都有可能给公司带来重大的损失,少扣了用户 ...
- 线上一次大量 CLOSE_WAIT 复盘
https://mp.weixin.qq.com/s/PfM3hEsDa3CMLbbKqis-og 线上一次大量 CLOSE_WAIT 复盘 原创 ms2008 poslua 2019-07-05 最 ...
- [Nginx笔记]关于线上环境CLOSE_WAIT和TIME_WAIT过高
运维的同学和Team里面的一个同学分别遇到过Nginx在线上环境使用中会遇到TIME_WAIT过高或者CLOSE_WAIT过高的状态 先从原因分析一下为什么,问题就迎刃而解了. 首先是TIME_WAI ...
- 分布式存储 FastDFS-5.0.5线上搭建
前言: 由于公司项目需要,最近开始学习一下分布式存储相关知识,确定使用FastDFS这个开源工具.学习之初,自己利用VMware虚拟机搭建了一个5台机器的集群,摸清了安装过程中可能出现的问 ...
- 线上Linux服务器运维安全策略经验分享
线上Linux服务器运维安全策略经验分享 https://mp.weixin.qq.com/s?__biz=MjM5NTU2MTQwNA==&mid=402022683&idx=1&a ...
- 【阿里云产品公测】OTS使用之简单线上产品实践基于PythonSDK
阿里云用户:morenocjm 实践是检验真理的唯一标准,学习技术需要通过实践过程中的不断尝试,才能够快速掌握要领.OTS是构建在阿里云飞天分布式系统之上的NoSQL数据库服务,提供海量结构化数据的存 ...
- 【微学堂】线上Linux服务器运维安全策略经验分享
技术转载:https://mp.weixin.qq.com/s?__biz=MjM5NTU2MTQwNA==&mid=402022683&idx=1&sn=6d403ab4 ...
随机推荐
- 基于 HTML5 Canvas 的 3D 模型贴图问题
之前注意到的一个例子,但是一直没有沉下心来看这个例子到底有什么优点,总觉得就是一个 list 列表,也不知道右边的 3d 场景放两个节点是要干嘛,今天突然想起来就仔细地看了一下这个例子的代码,实际操作 ...
- Bootstrap 开关(switch)使用整理
1.在JS里根据指定的 1或者0 或者其它值让按钮变成 on 或者 off (通常需要根据数据库查询的结果初始化开关的状态) (--开关插件包 bootstrap-switch.min.js) < ...
- 使用SpringBoot开发REST服务
本文介绍如何基于Spring Boot搭建一个简易的REST服务框架,以及如何通过自定义注解实现Rest服务鉴权 搭建框架 pom.xml 首先,引入相关依赖,数据库使用mongodb,同时使用red ...
- O(N^2)最长上升子序列
//最长上升子序列o(N^2)可以不连续的子序列, //状态为maxlen[i]表示以a[i]为终点最大上升子序列长度 #include<iostream> #include<cst ...
- (转)Python 日期和时间
转自http://www.runoob.com/python/python-date-time.html Python 日期和时间 Python 程序能用很多方式处理日期和时间,转换日期格式是一个常见 ...
- C# TreeView设置SelectedNode设置无效的问题
在设置Treeview.SelectedNode = newTreeNode(找到的TreeNode)时,界面上没呈现选择状态. 此时可能是treeview没有获取焦点,但是即使没有焦点,也可以让选中 ...
- 记录一次参加D2前端技术论坛的杭州之行
前言 在这里,闰土首先要感谢以下两位大佬提供的门票,分别是来自新浪微博部门的H同学,以及来自小米科技的D同学. 当我周六晚上在青旅写完这篇文章过后,第二天上网发现,已经有大佬提前一步在掘金上发布了高质 ...
- java内存模型个人理解总结
现阶段线程之间的通讯主要有两种:内存共享和消息传递,而且在java中是采用的内存共享.简单说下内存共享: 假设现在有a线程和b线程,在a和b线程之间的通讯是依靠a线程将相关数据刷新到共享内存,然后b线 ...
- 如何设置html中img宽高相同-css
最近项目中有一个问题,做一个响应式的盒子,随着屏幕的变化, 宽高一直保持相等,之前一直使用js动态设置,获取盒子的宽度来设置盒子高度. 但是加载时样式显示不是很好,后来直接用css实现. html部分 ...
- 使用AOP记录应用调用链开销
最近系统出现了一次线上的性能问题,本来以为目前的QPS应该是不会出现任何问题的,结果微服务还是比较容易因为某个点的问题导致雪崩的...出了性能问题就要做分析,正统的思路是要不断进行压测用JProfil ...