当请求通过负载均衡器发送并且响应太大而无法放入单个数据包时,为什么我没有收到响应?

当请求通过负载均衡器发送并且响应太大而无法放入单个数据包时,为什么我没有收到响应?

在某种情况下,我无法收到对特定服务的 HTTP 请求的响应:请求是通过负载平衡器发送的,并且响应太大而无法放入单个数据包中。在这些情况下,永远不会收到响应。两者都不是错误。服务器发送 TCP ACK 以响应包含 HTTP 请求的数据包,但之后什么也没有发生。连接只是挂起等待某些事情发生。无论请求是通过 CURL、节点的 HTTP 库还是 Postman 发送,都会观察到这种行为。

什么原因会导致这种行为?我该如何调试导致问题的原因?

  • 我已经验证负载均衡器后面的服务正在接收并响应 HTTP 请求,但是响应在某处丢失了。
  • 我们有其他具有类似设置的服务,但不会出现此问题。
  • 我们尝试设置负载均衡器的不同实例,但存在同样的问题。

在服务器上的 tshark 中,[TCP Retransmission]当它通过负载均衡器接收到一个有问题的请求后,我看到了一些条目(当直接接收到相同的请求时不会发生这种情况)。这似乎表明客户端和服务器之间的某些东西正在误导 TCP 流量(高度暗示负载均衡器),但我不明白是什么原因导致这种情况仅当 HTTP 响应被拆分成多个数据包时才会发生,并且仅由此特定服务发生。

导致失败的情况:

直接的 负载均衡器
单包
多个数据包

答案1

我发现了一个PMTUD 黑洞

我最初怀疑存在碎片问题,是因为 Cloudflare 发表了一篇关于封包分片。我使用 ping 发送不同大小的数据包确认了该问题:ping -s SIZE

首先我尝试了 1500,这是以太网的默认 MTU。

> ping 172.16.5.1 -s 1500

但什么也没发生。它只是挂起,什么也没打印。如果出现问题,您应该会收到如下错误:

ping: sendto: Message too long
Request timeout for icmp_seq 0

最终,我找到了一篇文章更详细地描述了这个问题并推荐了一个修复方法:设置/proc/sys/net/ipv4/tcp_mtu_probing1启用黑洞发现(在 Linux 中默认情况下未启用)

相关内容