nginx - 如何调试未关闭的 CLOSE_WAIT 连接的原因?(tcpdump 等)
问题描述
我们在同一台主机上安装了 Java 应用程序和 Nginx 作为反向代理。定期地,我们的CLOSE_WAIT
连接挂了很长时间:
$ ss -n4t | head
State Recv-Q Send-Q Local Address:Port Peer Address:Port
CLOSE-WAIT 1 0 127.0.0.1:8180 127.0.0.1:36599
CLOSE-WAIT 1 0 127.0.0.1:8180 127.0.0.1:36467
CLOSE-WAIT 1 0 127.0.0.1:8180 127.0.0.1:36154
而且它们的数量正在增加,然后应用程序就会出现问题。互联网说:
Your server is failing to detect client disconnects, or ignoring them, and not closing the socket.
Nginx 说:
2020/06/28 04:59:15 [error] 65506#0: *31719640 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 55.55.55.55, server: app.mycompany.com, request: "POST /url/url HTTP/1.0", upstream: "http://127.0.0.1:8180/url/url/provider", host: "app.mycompany.com"
好的,tcpdump
在正常行为期间显示:
2020-06-08 06:58:23.073139 IP 127.0.0.1.8180 > 127.0.0.1.57786: Flags [P.], seq 1:738, ack 1211, win 1365, options [nop,nop,TS val 2780380992 ecr 2780380974], length 737
2020-06-08 06:58:23.073233 IP 127.0.0.1.8180 > 127.0.0.1.57786: Flags [F.], seq 738, ack 1211, win 1365, options [nop,nop,TS val 2780380992 ecr 2780380992], length 0
2020-06-08 06:58:23.073302 IP 127.0.0.1.57786 > 127.0.0.1.8180: Flags [F.], seq 1211, ack 739, win 353, options [nop,nop,TS val 2780380992 ecr 2780380992], length 0
[F.]
从双方表示连接已正确关闭(基于图表)。
接下来,tcpdump
在异常行为期间(出生时CLOSE_WAIT
)显示:
2020-06-08 06:55:30.282015 IP 127.0.0.1.8180 > 127.0.0.1.57160: Flags [.], ack 1380, win 1365, options [nop,nop,TS val 2780208201 ecr 2780208201], length 0
2020-06-08 06:57:10.279006 IP 127.0.0.1.57160 > 127.0.0.1.8180: Flags [F.], seq 1380, ack 1, win 342, options [nop,nop,TS val 2780308198 ecr 2780208201], length 0
2020-06-08 06:57:10.318432 IP 127.0.0.1.8180 > 127.0.0.1.57160: Flags [.], ack 1381, win 1365, options [nop,nop,TS val 2780308238 ecr 2780308198], length 0
这里我们只看到一个[F.]
。
我已经阅读了数千篇文章,但仍然无法回答以下问题:
tcpdump[F.]
标志实际上是什么意思?文档说:Placeholder, usually used for ACK.
,但是第一个初始 FIN(没有 ACK)在哪里,例如:
this one? --> 2020-06-08 06:58:23.073233 IP 127.0.0.1.57786 > 127.0.0.1.8180: Flags [F], seq 738, ack 1211, win 1365, options [nop,nop,TS val 2780380992 ecr 2780380992], length 0
2020-06-08 06:58:23.073233 IP 127.0.0.1.8180 > 127.0.0.1.57786: Flags [F.], seq 738, ack 1211, win 1365, options [nop,nop,TS val 2780380992 ecr 2780380992], length 0
我的问题是,tcpdump
将 FIN 和 FIN/ACK 组合成[F.]
标志?如果是这样,在正常行为期间,我们会看到以下操作顺序:
- 客户端向服务器发送 FIN:
omitted by tcpdump
- 服务器向客户端发送 FIN/ACK:
127.0.0.1.8180 > 127.0.0.1.57786: Flags [F.]
- 服务器向客户端发送 FIN:
omitted by tcpdump
- 客户端向服务器发送 FIN/ACK:
127.0.0.1.57786 > 127.0.0.1.8180: Flags [F.]
如果是这样,在异常行为期间,客户端根本不会向我们发送 FIN,因此,我们的服务器不会发送 FIN/ACK,即[F.]
. 正确的?
第二个问题是 Nginx。据我了解netstat
:
CLOSE-WAIT 1 0 127.0.0.1:8180 127.0.0.1:36467
连接是从 localhost 到 localhost。是因为 Nginx 反向代理吗?这就是为什么我看不到真正的客户IP?如果是这样,Java-application 和 Nginx 之间会不会有问题?我之所以问,是因为我想调试/监视 HTTP 流量,包括从 localhost 到 localhost 的请求和响应标头以及消息正文:
tcpdump -A -s 0 'tcp port 8180 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' -i lo
因为我们在 Nginx 上有 SSL 终止,我相信我会看到服务器/客户端流内部发生了什么。第三个问题是,它是否正确/是否有更多方法可以清楚地理解我们得到“CLOSE_WAIT”的根本原因?
解决方案
推荐阅读
- python - 如何将pygame中的图像转换为numpy数组或数字?
- selenium-chromedriver - 如何使用 Playwright 更改默认语言 Chromium/Firefox?
- python - 单击窗口最大化/最小化按钮时如何自动调整小部件的大小?
- excel - Excel VBA更改页脚字体和字体大小
- mysql - MySQL如何使用检查?
- sql - 如何格式化 SQL 子查询以生成新旧数据
- docker - 如何从 s3 读取数据到 Kafka(Docker 镜像)
- ansible - 在“when:”条件语句中“搜索”一个字符串?
- python - Python tkinter 窗口显示消息
- python - 如何使用 datetime.index 使此函数在 python 数据框中工作