Node.js在处理大量并发连接时出现问题

7

我正在处理一个有些不寻常的应用程序,在这个应用中,10,000个客户端被准确地定时,每3分钟左右尝试同时提交数据。这个 'ab' 命令可以相当准确地模拟真实世界中的一个弹幕:

ab -c 10000 -n 10000 -r "http://example.com/submit?data=foo"

我正在使用Ubuntu 12.4上的Node.js,并在rackspacecloud VPS实例上收集提交内容,但是我发现Node.js存在一些非常奇怪的行为,即使我删除了所有业务逻辑并将http请求转换为no-op。测试进行到90%左右时,它会停顿很长时间。奇怪的是,这种情况在90%处始终如一-对于c=n=10k,在9000;对于c=n=5k,在4500;对于c=n=2k,在1800。测试最终完成,通常没有错误。但是ab和node日志都显示持续处理,直到测试运行的80-90%左右,然后才会完成。
当节点正常处理请求时,CPU使用率通常约为50-70%。在挂起期间,CPU占用率达到100%。有时它保持接近0。由于不稳定的CPU响应和它似乎与实际连接数量无关(仅与%完成相关),我不认为是垃圾收集器的问题。
我尝试在本地主机和远程服务器上运行'ab' - 效果相同。
我怀疑与TCP堆栈有关的某些事情,可能涉及关闭连接,但是我的配置更改都没有起作用。我的更改包括:
  • ulimit -n 999999
  • 当我listen()时,我将backlog设置为10000
sysctl更改如下:
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_max_orphans = 20000
net.ipv4.tcp_max_syn_backlog = 10000
net.core.somaxconn = 10000
net.core.netdev_max_backlog = 10000

我还注意到我倾向于在内核日志中收到这条消息:

TCP: Possible SYN flooding on port 80. Sending cookies.  Check SNMP counters.

我对这条消息感到困惑,因为TCP后备队列应该足够深,以免发生溢出。如果我禁用syn cookies,“发送cookie”会变成“丢弃连接”。

我猜测这是某种linux TCP堆栈调优问题,我已经阅读了网络上的所有内容,但似乎没有什么作用。有什么建议吗?

更新:尝试使用tcp_max_syn_backlog、somaxconn、netdev_max_backlog和listen()后备参数设置为50k,行为没有改变。依然会产生SYN洪泛警告。


2
顺便说一句,我对这个最终解决方案非常感兴趣,因为我也需要具有高数量活动连接的Node.js。 - Andrew T Finnell
1
说实话,尽管Node.js非常高效,但是一次性处理10k个连接的负载比我愿意让单个VPS承担的要大得多。 - Brad
如果您正在使用内置的 Node.js 集群来生成工作线程,请注意,向 server.listen() 传递自定义的 backlog 不会产生任何效果,即使在最新的 Node 版本中也是如此。存在一个 bug,当从工作进程调用 server.listen() 时,不会尊重您配置的 backlog,而是使用默认值 512。更多信息:github.com/nodejs/node/pull/33827 和 github.com/Unitech/pm2/issues/1786。 - Elad Nava
2个回答

3
你是否在运行node的同一台机器上运行ab?如果不是,你是否有1G或10G的网卡?如果是,则您是否真的正在尝试处理20,000个打开的连接?
此外,如果您将net.core.somaxconn更改为10,000,则该机器上绝对没有其他套接字打开吗?如果有,那么10,000不够高。
您是否尝试使用nodejs集群来分散每个进程中打开的连接数?

我已经在本地主机和另一台机器上都运行了ab。虽然本地主机上测试速度更快,但两种情况都表现出相同的暂停行为。暂停行为发生在8k和5k测试中(在2k测试中稍微有些),但我将使用somaxconn设置为50k重新运行测试。我计划使用这些机器的集群进行冗余和负载平衡,但这个测试是为了确定我需要多少实例。 - stickfigure
我已经使用参数设置为50k运行了测试,但行为没有改变。对我来说最令人惊讶的是SYN洪水警告;使用50k的后备队列设置,我不希望出现队列溢出。 - stickfigure
@stickfigure 请看一下这个答案 http://serverfault.com/questions/294209/possible-syn-flooding-in-log-despite-low-number-of-syn-recv-connections - Andrew T Finnell
如果您正在使用内置的Node.js cluster来生成工作线程,请注意,即使在最新的Node版本中,将自定义的backlog传递给server.listen()也没有效果。存在一个错误,当从工作进程调用server.listen()时,不会尊重您配置的backlog,而是使用默认的512。更多信息:https://github.com/nodejs/node/pull/33827和https://github.com/Unitech/pm2/issues/1786。 - Elad Nava

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接