我正在阅读 Node.js 中集群模块的文档:
http ://nodejs.org/api/cluster.html
它声称以下内容:
当多个进程都
accept()
在同一个底层资源上运行时,操作系统会非常有效地在它们之间进行负载平衡。
这听起来很合理,但即使经过几个小时的谷歌搜索,我也没有找到任何文章或任何东西可以证实这一点,或者解释这个负载平衡逻辑在操作系统中是如何工作的。
另外,什么操作系统在做这种有效的负载平衡?
我正在阅读 Node.js 中集群模块的文档:
http ://nodejs.org/api/cluster.html
它声称以下内容:
当多个进程都
accept()
在同一个底层资源上运行时,操作系统会非常有效地在它们之间进行负载平衡。
这听起来很合理,但即使经过几个小时的谷歌搜索,我也没有找到任何文章或任何东西可以证实这一点,或者解释这个负载平衡逻辑在操作系统中是如何工作的。
另外,什么操作系统在做这种有效的负载平衡?
“负载平衡”可能是一个有点糟糕的词选择,本质上它只是操作系统如何选择唤醒和/或接下来运行的进程的问题。通常,进程调度程序会尝试根据标准选择要运行的进程,例如将相同份额的 cpu 时间分配给具有相同优先级的进程、cpu/内存位置(不要在 cpu 周围反弹进程)等。无论如何,通过谷歌搜索你会发现很多关于进程调度算法和实现的资料。
现在,对于accept() 的特殊情况,这还取决于操作系统如何实现唤醒等待accept() 的进程。
一个简单的实现是唤醒在 accept() 调用中阻塞的每个进程,然后让调度程序选择它们运行的顺序。
以上很简单,但会导致“雷声”问题,因为只有第一个进程成功接受连接,其他进程又回到阻塞状态。一种更复杂的方法是让操作系统只唤醒一个进程。在这里,可以通过询问调度程序来选择唤醒哪个进程,或者仅通过在接受阻塞时()-for-this-socket 列表中选择第一个进程来选择。后者是十多年前 Linux 所做的,基于其他人已经发布的链接。
请注意,这只适用于阻塞 accept(); 对于非阻塞accept()(我确定这是node.js正在做的事情),问题就在于select()/poll()/whatever中哪个进程阻塞了事件。poll()/select() 的语义实际上要求所有这些都被唤醒,所以你又遇到了雷鸣般的羊群问题。对于 Linux,以及可能以类似方式具有系统特定高性能轮询接口的其他系统,可以通过使用单个共享 epoll fd 和边缘触发事件来避免雷鸣般的羊群。在这种情况下,事件将仅传递到 epoll_wait() 上阻塞的进程之一。我认为,类似于阻止accept(),选择将事件传递到的进程,
So at least for Linux, both for the blocking accept() and the non-blocking accept() with edge triggered epoll, there is no scheduling per se when choosing which process to wake. But OTOH, the workload will probably be quite evenly balanced between the processes anyway, as essentially the system will round-robin the processes in the order in which they finish their current work and go back to blocking on epoll_wait().