一 前提与背景
1 前提
只要出现CLOSE_WAIT累积一定是自己服务写的有问题
2 背景
给自己服务访问第三方服务加了连接池后,压测时候发现请求结束后有很多连接处于close_wait状态,且一直不结束
用连接池的原因是为了连接复用与连接控制
二 解决过程
1 知识点回顾
在正式解决该问题前,先回顾下“TCP四次挥手”过程
理解四次挥手时候不要用 服务端-客户端这样去理解每次挥手过程, 而是要以谁是主动断开连接的(即主动发送 FIN)为标准
2 服务是如何解决
如【背景】图所示,处于 CLOSE_WAIT的是【访问 8501接口】 和 【访问 80端口】的第三方服务连接。
-
问题1: 所以这里疑问来了,是我的服务主动访问第三方服务的,为什么会出现CLOSE_WAIT? -
答案1: 如【知识点回顾】所说, 要以谁是主动断开连接的来判断; 这里我的服务连接状态是CLOSE_WAIT,那么一定是我访问的第三方服务发送的FIN断开请求, 我是被动关闭了连接请求 -
问题2: 为啥CLOSE_WAIT 不释放 ? -
答案2: 一直处于CLOSE_WAIT 意味着 四次挥手过程中 第三次挥手一直没有挥手,也就是说我的服务一直没有给第三方服务发送FIN包
基于这个思路,那么第三方服务主动发送断开连接的情况可能是:第三方服务报错了(可能是超时,服务错误,连接问题等)。
看了下log 确实存在第三方服务报错。
证明了第一个问题后,第二问题“为什么我的服务不给第三方服务发送FIN包?”, 首先看下我的服务是如何写的
很简单的代码, POST访问第三方服务 + 异常判断与获取
可以理解是访问了第三方服务出错了,但是处于CLOSE_WAIT状态不变了, 也就是说一定需要我的服务主动给第三方服务发送FIN
了解到我的连接池中的连接,在访问第三方服务报错后,并不会主动断开连接,需要自己处理: 主动关闭出错的访问连接 。 简单的方案在执行完全部并发线程后关闭整个session
重启服务后测试发现服务CLOSE_WAIT状态的连接已经全部不在,当然不用担心新的连接问题,因为这次请求已经结束了,下次请求连接池会自动帮我们重新建立连接。
当然这里有更好的解决方案,例如只关闭出问题的连接,实际上都一样(对于我的调用逻辑)
三 总结
在使用长链接时候是经常会出现这样的情况,记住一点: 捕获异常,主动关闭出问题的连接
以上是自己个人的片面理解,主要为了记录。如果有误或者不全欢迎指正,非常感谢🙏
|