Node.js看起来很有趣,但我必须错过一些东西- Node.js不是调好只运行在一个进程和线程上吗?
那么如何针对多核cpu和多cpu服务器进行扩展呢?毕竟,单线程服务器的速度越快越好,但对于高负载,我希望使用多个cpu。同样的道理也适用于使应用程序更快——现在的方法似乎是使用多个cpu并并行化任务。
Node.js如何适应这种情况?它的想法是以某种方式分布多个实例还是什么?
Node.js看起来很有趣,但我必须错过一些东西- Node.js不是调好只运行在一个进程和线程上吗?
那么如何针对多核cpu和多cpu服务器进行扩展呢?毕竟,单线程服务器的速度越快越好,但对于高负载,我希望使用多个cpu。同样的道理也适用于使应用程序更快——现在的方法似乎是使用多个cpu并并行化任务。
Node.js如何适应这种情况?它的想法是以某种方式分布多个实例还是什么?
当前回答
您可以使用集群模块。检查这个。
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection
// In this case its a HTTP server
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}
其他回答
也可以将web服务设计为几个独立的服务器,它们侦听unix套接字,这样就可以将数据处理等功能推到单独的进程中。
这类似于大多数脚本/数据库web服务器架构,其中cgi进程处理业务逻辑,然后通过unix套接字将数据推入和拉入数据库。
不同的是,数据处理被写入一个节点web服务器监听端口。
它更复杂,但最终是多核开发的必经之路。为每个web请求使用多个组件的多进程架构。
您可以使用集群模块。检查这个。
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection
// In this case its a HTTP server
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}
集群模块允许您利用机器的所有核心。事实上,您可以使用非常流行的进程管理器pm2,在不修改代码的情况下,仅用两个命令就可以利用这一点。
npm i -g pm2
pm2 start app.js -i max
[这篇文章是最新的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)…}
单个端口的设置可以说有一些好处(进程之间的耦合可能更少,有更复杂的负载平衡决策,等等),但它肯定需要更多的工作来设置,内置的集群模块是一个低复杂性的替代方案,适用于大多数人。
我使用Node worker以一种简单的方式从我的主进程运行进程。在我们等待官方方式的时候,似乎工作得很好。