我们的(Linux)服务器在它的套接字上使用了{active, once}
选项,并且{tcp_error, Socket, etimedout}
消息。 我知道这可能是由于networking条件不好造成的,但是有一些奇怪的事情。
TCP keepalive在我们的机器上被全系统启用,实际的选项值是:
net.ipv4.tcp_keepalive_time = 1200 net.ipv4.tcp_keepalive_probes = 9 net.ipv4.tcp_keepalive_intvl = 75
这就意味着,我相信至less20分钟内套接字会超时。 但奇怪的是,我们的进程在不到10秒的时间内收到了{tcp_error, Socket, etimedout}
。
我想知道,这是由gen_tcp:send(...)
操作触发? 然后我发现它是不可能的,因为发送操作都是同步的,他们会立即失败。
所以,我的问题是,这个消息来自哪里? 或者究竟是什么触发了它? 我围绕Erlang VM的C源代码进行了inet_drv.c
,尤其是inet_drv.c
,但还没有结论。
谢谢。
tcpdump捕获显示这是TCP重新传输的超时事件。
我们的服务器机器将/proc/sys/net/ipv4/tcp_retries2
设置为5,这将导致5次重新传输中的连接断开,而在开发者机器上这个值默认为15,所以我们不能在本地重现问题。
从gen_tcp:send(...)
返回gen_tcp:send(...)
(或其他语言的等效API)仅意味着数据包被TCP堆栈接受,但不能保证它可以到达对等点,并且当你阻止其他操作。
在这里找到关于TCP重传的一些简要描述。