Node.js 在大量并发连接中苦苦挣扎

Posted

技术标签:

【中文标题】Node.js 在大量并发连接中苦苦挣扎【英文标题】:Node.js struggling with lots of concurrent connections 【发布时间】:2012-08-14 21:46:04 【问题描述】:

我正在开发一个有点不寻常的应用程序,其中 10,000 个客户端被精确计时,以尝试一次提交数据,每 3 分钟左右一次。这个“ab”命令相当准确地模拟了现实世界中的一个弹幕:

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

我在 rackspacecloud VPS 实例上的 Ubuntu 12.4 上使用 Node.js 来收集这些提交,但是,我看到 Node 的一些非常奇怪的行为,即使我删除了所有业务逻辑并将 http 请求转换为无操作。

当测试完成大约 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 响应和它似乎与实际连接数无关(仅 % 完成)之间,我不怀疑垃圾收集器。

我已经在 localhost 和远程服务器上尝试过这个运行 'ab' - 效果相同。

我怀疑某些与 TCP 堆栈有关的事情,可能涉及关闭连接,但我的配置更改都没有帮助。我的改变:

ulimit -n 999999 当我listen()时,我将积压设置为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 积压队列应该足够深,不会溢出。如果我禁用同步 cookie,“发送 cookie”会转到“断开连接”。

我推测这是某种 linux TCP 堆栈调整问题,我已经阅读了我在网上可以找到的所有内容。我尝试过的一切似乎都不重要。有什么建议吗?

更新: 尝试使用 tcp_max_syn_backlog、somaxconn、netdev_max_backlog 并将 listen() backlog 参数设置为 50k,但行为没有变化。仍然会产生 SYN 洪水警告。

【问题讨论】:

附带说明,我对最终解决方案非常感兴趣,因为我还需要具有大量活动连接的 nodejs。 就其价值而言,与 Node 一样高效,10k 连接同时做某事比我留给单个 VPS 的负载要多。 如果您使用内置的 Node.js 集群来生成工作线程,请注意将自定义积压工作传递给 server.listen() 将无效,即使在最新的 Node 版本中也是如此.有一个错误,当从工作进程调用 server.listen() 时,您配置的积压工作不被遵守,而是使用默认的 512。更多信息:github.com/nodejs/node/pull/33827 和 github.com/Unitech/pm2/issues/1786 【参考方案1】:

我认为您可能会发现这篇博文以及之前的博文很有用

http://blog.caustik.com/2012/08/19/node-js-w1m-concurrent-connections/

【讨论】:

【参考方案2】:

您是否在运行节点的同一台机器上运行 ab?如果没有,您有 1G 或 10G 网卡吗?如果是,那么您不是真的在尝试处理 20,000 个打开的连接吗?

另外,如果您将 net.core.somaxconn 更改为 10,000,那么您在该机器上绝对没有其他套接字打开?如果你这样做,那么 10,000 还不够高。

您是否尝试过使用nodejs 集群来分散每个进程的打开连接数?

【讨论】:

我在本地主机和另一台机器上都运行了 ab。尽管测试在 localhost 上运行得更快,但这两种情况都表现出相同的暂停行为。暂停行为发生在 8k 和 5k 测试中(在较小程度上发生在 2k 测试中),但我将在 somaxconn 设置为 50k 的情况下重新运行测试。我确实计划使用这些机器的集群来实现冗余和负载平衡,但这个测试是为了弄清楚我需要多少个实例。 我已经运行测试,参数设置为 50k,行为没有改变。最让我惊讶的是 SYN 泛洪警告;积压设置为 50k 我不希望溢出队列。 @stickfigure 看看这个答案serverfault.com/questions/294209/… 如果您使用内置的 Node.js cluster 来生成工作线程,请注意将自定义 backlog 传递给 server.listen() 将无效,即使在最新版本中也是如此节点版本。有一个错误,当从工作进程调用 server.listen() 时,您配置的积压工作不被遵守,而是使用默认的 512。更多信息:github.com/nodejs/node/pull/33827 和 github.com/Unitech/pm2/issues/1786

以上是关于Node.js 在大量并发连接中苦苦挣扎的主要内容,如果未能解决你的问题,请参考以下文章

50.000 个并发连接的 Node.js 系统要求

Node.js 异步编程与连接mysql数据库

Node.js究竟是什么?

线程、事件循环和大量连接和并发

Socket.io:WebSockets 可以处理多少并发连接?

Node.js:浅析高并发与分布式集群