Min*_*ius 4 networking http nginx reverse-proxy
我收到代理服务器返回的零星 502 错误。在检查数据包流时,我看到 nginx 向源服务器已发送 [FIN,ACK] 的套接字发送 POST 请求。我想了解这是如何可能的以及任何潜在的解决方案。是源端的问题(发送响应后 5 秒后才发送 FIN、ACK)还是代理的问题?
我的理解:
问题:
我不拥有原产地 - 所以无法捕获那里。
额外细节:
代理上的错误日志(nginx错误日志):
2017/04/17 06:51:07 [error] 123091#0: *225010841 upstream prematurely closed connection while reading response header from upstream, client: X.90.10, server: www.example.com, request: "POST /web/?a=b HTTP/1.1", upstream: "http://X.32.238:80/web/?a=b", host: "www.example.com"
Run Code Online (Sandbox Code Playgroud)
此屏幕截图中显示了最后一个请求的 SEQ 和 ACK 编号:
此案可能的解释是什么?
源上大约 5 秒的空闲计数器与可变的客户端活动之间的竞争条件。第三个涉及的变量当然是网络延迟。
源上似乎有大约 5 秒的空闲计时器,而您的客户端需要大约 5 秒的时间通过 Nginx 代理发出第二个请求 (POST)。如果前者比后者长(包括网络延迟),则没有问题。如果发送客户端请求只需要多一点时间,那么您就会遇到问题。
您可以看到来自 Nginx 的 POST 和 FIN、ACK 几乎是一起发送的:分别在源端的 FIN、ACK 之后 2.4 毫秒和 2.6 毫秒。这可能会让您偏离正轨,因为我认为 POST 根本不是对源端 FIN、ACK 的响应。由于是在源端FIN、ACK后2.4ms发送的
如果代理(nginx)已经收到 FIN 并且实际上正在确认它,为什么它还要发送另一个请求!(POST [PSH, ACK] 数据包中的确认编号实际上是 [FIN,ACK] 的 SEQ_NUMBER + 1 - 因此它正在确认虚拟位 FIN。
POST 数据包上的 ACK 编号很可能是“200 OK”数据包的编号。在该 HTTP 响应之后,没有来自服务器端的额外数据,因此来自客户端的任何 ACK 都将确认相同的数字。
更新:我们现在知道 POST 数据包的 ACK 号增加了 1,因此 Nginx 知道 [FIN,ACK]。进一步的调查显示这很好:如果机器在收到远程端的响应后不打算继续连接,则它可能会发送请求并以 [FIN,ACK] 结束,远程端将发送请求的数据并结束继续[FIN,ACK]过程。
这并没有改变这样一个事实:存在竞争条件,源端决定在 5 秒空闲后关闭连接,从而忽略随后不久出现的 POST 数据包(甚至发送回 RST - 尽管尚不清楚此 RST 是否会无论如何都已发送)。
源端仅在 5 秒后而不是立即返回 [FIN,ACK] 的可能原因是什么?读取超时/空闲超时?
您不必立即返回 FIN,ACK,特别是自 HTTP 1.1 和持久连接的引入以来。这大约 5 秒似乎是原点上的空闲计时器。
这两件事都在这里得到确认:https://en.wikipedia.org/wiki/HTTP_persistent_connection - 包括 Apache 2.2 或更高版本中默认的 5 秒空闲超时。
建议的解决方案
如果不了解更多关于您的基础设施的信息,我无法真正提出解决方案,但粗略地说,您有几个选择:
希望这可以帮助 :)
| 归档时间: |
|
| 查看次数: |
6032 次 |
| 最近记录: |