Node.js看起来很有趣,但我必须错过一些东西- Node.js不是调好只运行在一个进程和线程上吗?
那么如何针对多核cpu和多cpu服务器进行扩展呢?毕竟,单线程服务器的速度越快越好,但对于高负载,我希望使用多个cpu。同样的道理也适用于使应用程序更快——现在的方法似乎是使用多个cpu并并行化任务。
Node.js如何适应这种情况?它的想法是以某种方式分布多个实例还是什么?
Node.js看起来很有趣,但我必须错过一些东西- Node.js不是调好只运行在一个进程和线程上吗?
那么如何针对多核cpu和多cpu服务器进行扩展呢?毕竟,单线程服务器的速度越快越好,但对于高负载,我希望使用多个cpu。同样的道理也适用于使应用程序更快——现在的方法似乎是使用多个cpu并并行化任务。
Node.js如何适应这种情况?它的想法是以某种方式分布多个实例还是什么?
当前回答
Ryan Dahl在去年夏天谷歌的技术演讲中回答了这个问题。换句话说,“只需运行多个节点进程,并使用一些合理的方法来允许它们进行通信。例如sendmsg()风格的IPC或传统的RPC”。
如果你想马上动手,看看spark2 Forever模块。它使得生成多个节点进程变得非常容易。它处理端口共享的设置,所以它们可以接受到同一个端口的连接,如果你想确保进程在死亡时重新启动,也可以自动重生。
更新:10/11/11:节点社区的共识似乎是,集群现在是管理每台机器的多个节点实例的首选模块。《永远》也值得一看。
其他回答
Ryan Dahl在去年夏天谷歌的技术演讲中回答了这个问题。换句话说,“只需运行多个节点进程,并使用一些合理的方法来允许它们进行通信。例如sendmsg()风格的IPC或传统的RPC”。
如果你想马上动手,看看spark2 Forever模块。它使得生成多个节点进程变得非常容易。它处理端口共享的设置,所以它们可以接受到同一个端口的连接,如果你想确保进程在死亡时重新启动,也可以自动重生。
更新:10/11/11:节点社区的共识似乎是,集群现在是管理每台机器的多个节点实例的首选模块。《永远》也值得一看。
可以使用纯TCP负载均衡器(HAProxy)将NodeJS扩展到多个盒子,每个盒子运行一个NodeJS进程。
如果你有一些共同的知识在所有实例之间共享,你可以使用一个中央Redis存储或类似的,然后可以从所有流程实例访问(例如从所有盒子)
[这篇文章是最新的2012-09-02(比上面更新)。]
Node.js绝对可以在多核机器上扩展。
是的,Node.js是一个线程一个进程。这是一个非常深思熟虑的设计决策,消除了处理锁定语义的需要。如果您不同意这一点,那么您可能还没有意识到调试多线程代码是多么困难。要了解Node.js进程模型的更深层次的解释,以及为什么它是这样工作的(以及为什么它永远不支持多线程),请阅读我的另一篇文章。
那么我如何利用我的16核盒子呢?
两种方式:
For big heavy compute tasks like image encoding, Node.js can fire up child processes or send messages to additional worker processes. In this design, you'd have one thread managing the flow of events and N processes doing heavy compute tasks and chewing up the other 15 CPUs. For scaling throughput on a webservice, you should run multiple Node.js servers on one box, one per core and split request traffic between them. This provides excellent CPU-affinity and will scale throughput nearly linearly with core count.
在web服务上扩展吞吐量
因为v6.0。X node .js已经包括了开箱即用的集群模块,这使得设置多个可以侦听单个端口的节点工作者变得很容易。注意,这与npm提供的旧的learnboost“cluster”模块不同。
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
http.Server(function(req, res) { ... }).listen(8000);
}
工人们将竞相接受新的连接,负载最少的流程最有可能胜出。它工作得非常好,可以在多核设备上很好地扩展吞吐量。
如果你有足够的负载来关心多个核,那么你也会想做更多的事情:
运行你的Node.js服务在像Nginx或Apache这样的web代理之后——它可以做连接节流(除非你想让过载条件完全关闭),重写url,提供静态内容,并代理其他子服务。 定期回收工作进程。对于长时间运行的进程,即使是很小的内存泄漏最终也会累积起来。 设置日志收集/监控
PS:在另一篇文章的评论中有亚伦和克里斯托弗之间的讨论(写这篇文章时,它是第一篇文章)。这里有几点评论:
A shared socket model is very convenient for allowing multiple processes to listen on a single port and compete to accept new connections. Conceptually, you could think of preforked Apache doing this with the significant caveat that each process will only accept a single connection and then die. The efficiency loss for Apache is in the overhead of forking new processes and has nothing to do with the socket operations. For Node.js, having N workers compete on a single socket is an extremely reasonable solution. The alternative is to set up an on-box front-end like Nginx and have that proxy traffic to the individual workers, alternating between workers for assigning new connections. The two solutions have very similar performance characteristics. And since, as I mentioned above, you will likely want to have Nginx (or an alternative) fronting your node service anyways, the choice here is really between:
共享端口:nginx(端口80)——> Node_workers x N(共享端口3000w / Cluster)
vs
单个端口:nginx(端口80)——> {Node_worker(端口3000),Node_worker(端口3001),Node_worker(端口3002),Node_worker(端口3003)…}
单个端口的设置可以说有一些好处(进程之间的耦合可能更少,有更复杂的负载平衡决策,等等),但它肯定需要更多的工作来设置,内置的集群模块是一个低复杂性的替代方案,适用于大多数人。
Spark2基于Spark,目前已不再维护。集群是它的继承者,它有一些很酷的特性,比如每个CPU核心生成一个工作进程,以及重生死亡的工作进程。
一种方法是在服务器上运行多个node.js实例,然后在它们前面放置一个负载均衡器(最好是非阻塞的,如nginx)。