为什么 nginx 在客户端 FIN 收到后不立即关闭连接?

为什么 nginx 在客户端 FIN 收到后不立即关闭连接?

问题: 我们已将 CDN 提供商设置为静态图像文件服务器的代理。几个小时后,我们发现 TCP SYN 丢失率极高,孤立连接数量异常高。

为了解决问题而采取的观察方法: 我捕获了 1.5 秒的服务器流量并检查了一些图像下载。可疑的是,nginx(几乎配置为默认设置)正在使用 ACK 而不是 FIN/ACK 响应 CDN 服务器的 FIN 数据包。在 nginx 发出 ACK 后,连接端口上整整一秒钟没有响应,这意味着服务器没有其他内容可发送。由于流量很大,我无法捕获超过 1.5 秒的数据。

以下是示例 TCP 连接的摘要:

No.     Time        Source      Destination Proto   Length and Info 
20      0.004281671 [CDN IP]    [NGINX IP]  TCP     74  20200 → 443 [SYN] Seq=0 Win=28400 Len=0 MSS=1420 SACK_PERM=1 TSval=2822189024 TSecr=0 WS=1024
21      0.004333161 [NGINX IP]  [CDN IP]    TCP     74  443 → 20200 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=2611883387 TSecr=2822189024 WS=128
372     0.125341624 [CDN IP]    [NGINX IP]  TCP     66  20200 → 443 [ACK] Seq=1 Ack=1 Win=28672 Len=0 TSval=2822189148 TSecr=2611883387
373     0.125357371 [CDN IP]    [NGINX IP]  TLSv1.2 287 Client Hello
374     0.125367976 [NGINX IP]  [CDN IP]    TCP     66  443 → 20200 [ACK] Seq=1 Ack=222 Win=30080 Len=0 TSval=2611883417 TSecr=2822189149
392     0.127328681 [NGINX IP]  [CDN IP]    TLSv1.2 2882    Server Hello, Certificate
393     0.127339623 [NGINX IP]  [CDN IP]    TLSv1.2 233 Server Key Exchange, Server Hello Done
645     0.244326565 [CDN IP]    [NGINX IP]  TCP     66  20200 → 443 [ACK] Seq=222 Ack=2984 Win=34816 Len=0 TSval=2822189267 TSecr=2611883418
646     0.244353033 [CDN IP]    [NGINX IP]  TLSv1.2 192 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
647     0.244630520 [NGINX IP]  [CDN IP]    TLSv1.2 324 New Session Ticket, Change Cipher Spec, Encrypted Handshake Message
1121    0.360323576 [CDN IP]    [NGINX IP]  TLSv1.2 1496    Application Data    
1122    0.360373767 [NGINX IP]  [CDN IP]    TCP     66  443 → 20200 [ACK] Seq=3242 Ack=1778 Win=33024 Len=0 TSval=2611883476 TSecr=2822189383
1123    0.360539425 [NGINX IP]  [CDN IP]    TLSv1.2 392 Application Data    
1124    0.360614290 [NGINX IP]  [CDN IP]    TLSv1.2 97  Encrypted Alert 
1554    0.477351117 [CDN IP]    [NGINX IP]  TCP     78  [TCP Window Update] 20200 → 443 [ACK] Seq=1778 Ack=3242 Win=40960 Len=0 TSval=2822189500 TSecr=2611883447 SLE=3568 SRE=3600
1555    0.477369934 [CDN IP]    [NGINX IP]  TCP     66  20200 → 443 [ACK] Seq=1778 Ack=3600 Win=43008 Len=0 TSval=2822189501 TSecr=2611883476
1596    0.505356016 [CDN IP]    [NGINX IP]  TCP     66  20200 → 443 [FIN, ACK] Seq=1778 Ack=3600 Win=43008 Len=0 TSval=2822189530 TSecr=2611883476
1597    0.505368886 [NGINX IP]  [CDN IP]    TCP     66  443 → 20200 [ACK] Seq=3600 Ack=1779 Win=33024 Len=0 TSval=2611883512 TSecr=2822189530

另外,我猜想 CDN 服务器使用 HTTP keep-alive 标头。我不确定的分析是 CDN 端的错误配置使其为每个图像使用一个连接并发送 keep-alive 标头。它使 nginx 让 TCP 保持活动状态,并且 FIN 数据包仅由 ACK 响应。然后一个解决方法是将 nginx keep-alive 超时减少到 1 秒。

问题:这个问题的具体原因是什么?或者我应该做哪些改变来解决这个问题?

答案1

是什么问题你想解决吗?

孤立连接和“SYN 丢失”其实不是问题。据我观察,NGINX 很少关心这些细节。

您添加了 CDN。并且该 CDN 不是用户. 因此它的行为有所不同。

您可能已经用完了池中的连接空间。请增加该空间。

请发布更具体的问题以获得更多清晰度。

答案2

我检查了请求的内容后发现,nginx 的行为是由于 CDN 的行为造成的。因为 CDN 使用的是保持活动连接,而 nginx 中保持活动连接的持续时间设置为 60 秒左右。当我将其减少到 15 秒时,情况恢复正常。

相关内容