【发布时间】:2016-10-21 11:59:20
【问题描述】:
在尝试并行建立大量 TCP 连接时,我观察到一些奇怪的行为,我认为gen_tcp 中存在潜在错误。
该场景是一个服务器在一个具有多个并发接受器的端口上侦听。从客户端我通过调用gen_tcp:connect/3 建立连接,然后我向服务器发送“Ping”消息并在被动模式下等待“Pong”响应。按顺序执行 'get_tcp:connect/3' 调用时一切正常,包括大量连接(我测试了高达 ~ 28000)。
在尝试建立大量并行连接时会出现问题(取决于大约 75 到数百台机器)。虽然大多数连接仍然建立,但一些连接失败并在gen_tcp:recv/3 中出现closed 错误。奇怪的是,这些连接之前没有失败,对gen_tcp:connect/3 和gen_tcp:send/2 的调用都成功了
(即返回ok)。在服务器端,我没有看到这些“奇怪”连接的匹配连接,即没有返回 gen_tcp:accept/1。我的理解是,成功的 'get_tcp:connect/3' 应该会在服务器端产生匹配的接受连接。
我已经提交了bug report,在那里你可以找到更详细的描述和一个最小的代码示例来演示这个问题。我能够在 Linux 和 Mac OS X 以及不同的 Erlang 版本上重现该问题。
我的问题是:
- 是否有人能够重现该问题并确认这是错误行为?
- 有解决方法的想法吗?如何处理这个问题,其他顺序启动所有连接(这需要永远)?
【问题讨论】:
-
不看示例,我首先想到的是 tcp
backlog的大小可能太小了。你试过提升它吗? (erlang.org/doc/man/gen_tcp.html#listen-2) 请参阅 veithen.github.io/2014/01/01/… 了解它的作用。 -
我同意@johlo。我查看了您的代码,但您没有使用
{backlog, B}选项。 Erlang TCP sockets get closed 的可能重复项 -
@johlo 谢谢,很棒的提示和很棒的链接。增加 backlog 解决了这个问题,文章解释了为什么对
gen_tcp:connect/3的调用没有错误返回(因为它从服务器获得了 SYN/ACK 并发送了最终的 ACK),但服务器最终没有处于建立状态(因为它忽略了最后的 ACK)。 -
我根据@johlo 的建议开始回答这个问题。随时帮助改进答案。我仍然有点不清楚为什么仅在客户端尝试接收而不是发送时才发现问题。这是否特定于发送和接收的工作方式?或者这是由于时间问题(尝试发送时服务器仍在重试
SYN-ACKs)?