[技术求教] 如何主动杀死一个 tcp 连接?请大家帮我分析分析。

11 天前
 aizya

问题背景

我开发了一个 Web 系统,有一个功能需要提供一个 HTTP REST 接口供设备端调用,我的 Web 用 Java 开发,设备的用的是 Labview ,他的代码具体怎么实现我不清楚。

系统在运行一段时间后,客户反馈 HTTP 接口偶发调用失败,但是我通过查询日志,发现在上报接口无法调用的时刻,后台日志中接口都没有被触发。这个时候想到了看一下 TCP 连接数,监控发现 Web 系统有很多 CLOSE_WAIT 的 TCP 连接。

netstat -an | grep "8080" | grep 'CLOSE_WAIT'

后面发现一个规律,随着 CLOSE_WAIT 连接越来越多,各个设备反馈接口无法调用的频率也随之增多。

排查过程

  1. 先分析服务端的 CLOSE_WAIT 连接,发现一个特别怪异的事,服务端存在某个客户端(设备)的连接,但是在设备端,同样执行 netstat ,居然没有与服务端对应的 tcp 连接。从表象上来说,客户端不知道用什么方式杀死了连接,服务端还保留了 socket 。很奇怪啊,按照正常的逻辑,客户端应该存在很多 FIN-WAIT-2 的连接。

  1. 于是分别在出问题的情况下,使用 tcpdump 和 wirehark 抓了服务器和某几个存在 CLOSE_WAIT 连接的设备的网络包,发现在设备端反馈 FIN 关闭连接时,会出现一个 RST 的帧,并且 8080 不会回 FIN,只会 ACK ,导致 CLOSE_WAIT 的出现。但是,这种问题具体出现的原因,我一直想不明白。

  1. 经过一番折腾,我考虑能不能通过服务器配置或者主动杀死 tcp 连接的方式减少 CLOSE_WAIT 连接,来尽可能减少 CLOSE_WAIT 堆积引起的高频率 CLOSE_WAIT 问题(解决不了问题,就解决出现问题的地方)。 我采用的是 killcx https://killcx.sourceforge.net/ ,来模拟 SYNC ,主动关闭连接。但是,不出意外,还是除了意外,连接关不掉!!!其他的连接都可以,但是就是 CLOSE_WAIT 的无法关闭。

  2. 最后,只能定时重启 JAVA 程序,主动释放连接才能恢复,在重启的三四天时间不会有问题,过了一个时间点,这个问题又出问题了。。。周而复始。。。

请大家帮忙分析分析,为啥会出现服务器( Linux )保持了 TCP 连接,但是客户端( Windows )没有。到底是我 JAVA 应用的问题,还是网络问题抑或者是客户端关闭连接的问题?给提供点思路,拜求了!

1805 次点击
所在节点    程序员
24 条回复
seedhk
10 天前
CLOSE_WAIT 很明显就是服务端问题
导出线程栈信息,找到所有 CLOSE_WAIT 的线程,看堆栈找对应代码
iceheart
10 天前
客户端没连接是因为已经 close 了,
客户端 close 了服务端才有 CLOSE_WAIT
服务端收到断开通知就要 close
CLOSE_WAIT 的字面意思就是 等待(应用程序) 来调用 close
palfortime
9 天前
@aizya 不了解这个框架,你可以试一下跑个测试的服务,让客户端的进程跑一个请求就退出,看看会不会产生。
可以在服务端 jstack 一下,看看有没有工作线程是卡住了。可能由于工作线程卡住,导致框架无法处理 close 请求。
同时可以在服务端加载一下 opentelemetry 的 javaagent 收集一下 trace 和 metric ,看看是否有服务端的异常。
xxxbin
9 天前
有意思。那么各位大佬,CLOSE_WAIT 的 tcp 该咋关?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1079318

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX