我们的(Linux)服务器使用选项{active, once}
和它的套接字,并且弹出{tcp_error, Socket, etimedout}
条消息。我知道这可能是由糟糕的网络状况引起的,但有一些奇怪的事情。
TCP keepalive在我们的机器上已在系统范围内启用,实际选项值为:
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
这意味着套接字会在至少20分钟内超时,我相信。但奇怪的是,我们的流程在不到10秒的时间内就收到了{tcp_error, Socket, etimedout}
。
我想知道它是由gen_tcp:send(...)
操作引发的吗?然后我发现这是不可能的,因为发送操作都是同步的,它们会立即失败。
所以,我的问题是,etimedout
消息来自哪里?或是什么引发了它?我围绕着Erlang VM的C源代码,特别是inet_drv.c
,但还没有结论。
感谢。
答案 0 :(得分:3)
tcpdump捕获显示它是来自TCP重新传输的超时事件。
我们的服务器计算机将/proc/sys/net/ipv4/tcp_retries2
设置为5,这会导致5次重新传输断开连接,而此值在开发者计算机上默认为15,因此我们无法在本地重现该问题。
从gen_tcp:send(...)
(或其他语言中的等效API)返回仅意味着TCP堆栈接受该数据包,但无法保证它可以到达对等体,并且当您遇到错误时,错误可能会被挽救阻止其他行动。
找到有关TCP重新传输here的一些简要说明。