一、问题现象
背景:公司封装了消息中心,统一对接外部短信通道,并提供统一的发送API(http接口),供公司内部使用。
环境如下:
问题现象:图中“3.短信平台” 出现很多 closed_wait 连接,查看这些closed_wait的连接都是和nginx的连接ip:port
二、分析http在什么情况下会出现closed_wait
来看一下http状态变化图:
1、首先close_wait是出现在服务端的,生产的问题是,nginx调用短信平台tomcat 失败,此时短信平台即是 “服务端”【其实我首先是百度的,百度很多都是说连接为关闭,可是close_wait 是在服务端,服务端我现在用的是spring_mvc,不存在这个问题… 没办法,只能自己来分析了… 】
2、根据上图可知,当客户端主动关闭连接,发起 FIN 包时,服务端此时则处于 close_wait状态,当服务端发送ACK、FIN后,服务端才会处于 closed 状态,那问题是为什么服务端不发送ACK、FIN报文呢?客户端什么情况下会主动关闭连接呢?
3、客户端主动关闭连接,服务端不发送ACK、FIN报文…
怀疑是否因为服务端阻塞了,客户端超时后关闭连接
不如现在本地测试下,经过测试,通过jmeter调用本地tomcat,并设置超时时间为5s,然后在本地代码打上一个断点,这样服务端就不会响应客户端了。经测试果然如此,在5s后,服务端的端口连接状态为CLOSED_WAIT,客户端的连接状态为:FIN_WAIT_2,和我们的猜想一致。
4、那么服务端为什么会阻塞呢?接下来我们到生产环境每隔几秒钟下载一个jstack文件,结果发现所有http连接全都处于阻塞状态。至此问题排查清楚:由于服务端代码有锁问题,导致所有http连接都阻塞在获取锁的地方,客户端调用超时后,主动关闭连接,发送FIN报文,服务端由于阻塞无法响应FIN报文,导致服务端 close_wait的连接很多。