我正在运行一个相当大规模的Node.js 0.8.8应用程序,它使用集群,在一个16处理器的机器上有16个工作进程和超线程(所以32个逻辑核心)。我们发现,自从迁移到Linux 3.2.0内核(从2.6.32开始)以来,工作器子进程之间传入请求的平衡似乎主要集中在5个左右的进程上,而其他11个进程根本不做太多工作。这可能对吞吐量更有效,但似乎增加了请求延迟,并且对我们来说并不是最优的,因为这些连接中的许多都是可以同时开始工作的长期websocket连接。
子进程都在一个套接字上接受(使用epoll),虽然这个问题在Node0.9 (https://github.com/bnoordhuis/libuv/commit/be2a2176ce25d6a4190b10acd1de9fd53f7a6275)中有一个修复,但这个修复似乎对我们的测试没有帮助。有没有人知道内核调优参数或构建选项可能会有帮助,或者我们最好还是回到2.6内核,或者使用不同的方法在工作进程之间进行负载平衡?
我们将其归结为一个简单的HTTP围攻测试,但请注意,这是在一个具有超线程(即24个逻辑核心)的12核机器上运行12个proc,并在套接字上接受12个工作进程,而不是生产中的16个procs。
Debian Squeeze上节点0.9.3的HTTP围攻,裸机上2.6.32内核的HTTP围攻:
reqs pid
146 2818
139 2820
211 2821
306 2823
129 2825
166 2827
138 2829
134 2831
227 2833
134 2835
129 2837
138 2838除了3.2.0内核之外,一切都是一样的:
reqs pid
99 3207
186 3209
42 3210
131 3212
34 3214
53 3216
39 3218
54 3220
33 3222
931 3224
345 3226
312 3228发布于 2012-12-19 22:40:55
不要依赖操作系统的socket multiple accept来平衡web服务器进程之间的负载。
Linux内核的行为因版本而异,我们在3.2内核中看到了一个特别不平衡的行为,在以后的版本中似乎更加平衡。例如3.6。
我们是在这样的假设下运行的,即应该有一种方法可以让Linux用这种方式来做一些类似于循环的事情,但是这样做有很多问题,包括:
可能存在问题
您可以在github问题上详细查看我们的测试,我们使用它来与优秀的Node.js团队通信,从这里开始:https://github.com/joyent/node/issues/3241#issuecomment-11145233
谈话结束时,Node.js团队表示,他们正在认真考虑在集群中实现显式循环调度,并为此开始了一个问题:https://github.com/joyent/node/issues/4435,以及Trello团队(也就是我们)将采用我们的后备计划,即使用本地HAProxy进程跨每台服务器计算机上的16个端口进行代理,每个端口上运行一个2-worker-process集群实例(以便在进程崩溃或挂起的情况下在接受级别进行快速故障转移)。该计划运行良好,大大减少了请求延迟的变化,并降低了平均延迟。
这里还有更多要说的,我没有采取邮寄Linux内核邮件列表的步骤,因为不清楚这是否真的是Xen或Linux内核问题,或者真的只是对我们的多重接受行为的错误预期。
我很希望看到专家对multiple accept的回答,但我们将回到我们可以使用我们更好地理解的组件来构建什么。如果有人发布了更好的答案,我将很高兴接受它,而不是我的。
https://stackoverflow.com/questions/13770826
复制相似问题