我正在通过代理服务器返回零星的502s。 当检查数据包stream时,我看到nginx发送POST请求到源服务器已经发送[FIN,ACK]的套接字。 我想了解这是如何可能和任何潜在的解决scheme。 原始问题(发送响应后5秒发送FIN还是ACK)还是代理服务器?
下面是PCAP的屏幕截图,说明问题:
我的理解:
题:
我没有自己的起源 – 所以不能在那里捕捉。
额外细节:
代理(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"
在此屏幕截图中显示最后一个请求的SEQ和ACK号码:
这种情况可能的解释是什么?
起始点上约5秒空闲计数器与客户端可变活动之间的竞争条件。 第三个涉及variables当然是networking延迟。
似乎有一个约5秒的空闲计时器在原点,而你的客户端需要约5秒钟通过Nginx代理发出第二个请求(POST)。 如果前者比后者长(包括networking延迟),则没有问题。 如果发送客户请求只需要多一点点,那么你就有问题了。
你可以看到POST和FIN,来自Nginx的ACK如何被发送到一起:分别在源的FIN,ACK之后2.4ms和2.6ms。 这可能会让你失望,因为我不认为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秒后closures连接,从而忽略不久之后发送的POST数据包(甚至发送RST返回 – 虽然目前还不清楚这个RST是否会已经被发送不pipe)。
5秒后,原点返回[FIN,ACK]而不是直接返回的可能原因是什么? 读取超时/空闲超时?
您不必立即返回FIN,ACK,特别是自HTTP 1.1和持久连接的引入以来。 这些〜5秒似乎是原点上的一个空闲计时器。
这两件事情都在这里证实: https : //en.wikipedia.org/wiki/HTTP_persistent_connection – 包括在Apache 2.2或更新的默认5秒空闲超时。
build议解决scheme
如果不了解更多有关基础设施的知识,我无法真正提出解决scheme,但粗略地说,您有几个select:
希望这可以帮助 :)