【发布时间】:2017-02-01 11:41:50
【问题描述】:
TCP 有一个 keep-alive 机制来检测死连接,但令我惊讶的是这个选项在默认情况下是关闭的,而且许多库/工具不使用这个特性。
如果我理解正确,如果来自对等方的所有 FIN/RST 数据包都已丢失,则在 recv 调用中阻塞的 TCP 连接将无法检测连接是否已被对等方实际中止。
客户端的超时参数可能会缓解此问题,但许多库也没有设置超时的选项。一个例子是 mysql-python 连接器没有 recv 超时选项。另一个例子是 Nginx 服务器使用 proxy_pass 与 gunicorn 后端通信,gunicorn worker 可能会由于其上的死连接而停止响应,但 gunicorn worker 无法检测到它。
如果我错了,谁能解释原因或纠正我?
【问题讨论】:
-
你的问题是建立在一个谬误之上的。不使用 TCP keepalive 与不检测死连接不同。没有必要使用 TCP keepalive 来检测死连接。还有其他方法。例如,检测“连接重置”是绝对可靠的,而且我从未遇到过没有这样做的库。如果您可以生成“许多”不提供 keepalive 或读取超时的库示例,请这样做。
-
您能否解释一下为什么检测“连接重置”是可靠的?如果来自对等方的 RST 数据包都丢失了怎么办?在没有使用 tcp keepalive 的情况下,recv 操作中的客户端如何知道这种情况?
-
来自对等方的 RST 不是连接重置的唯一原因。如果足够多的发送和重试未得到确认,本地主机将自行重置连接。如果客户除了
recv()什么都不做,我已经建议了读取超时, -
timeout 不适用于具有持久连接的服务器端,反向 Web 代理使用到 fastcgi 或某些 wsgi 服务器的持久连接是很常见的。 Fastcgi/wsgi 服务器不断接收来自对等方的请求,读取超时没有意义。