Node.js看起来很有趣,但是我必须错过一些东西-Node.js是否仅调整为仅在单个进程和线程上运行?
那么它如何扩展到多核CPU和多CPU服务器?毕竟,使速度尽可能快的单线程服务器非常好,但是对于高负载,我想使用多个CPU。对于提高应用程序速度也是如此-今天看来,方法是使用多个CPU并使任务并行化。
Node.js如何适合这张图片?它的想法是以某种方式分发多个实例还是什么?
Node.js看起来很有趣,但是我必须错过一些东西-Node.js是否仅调整为仅在单个进程和线程上运行?
那么它如何扩展到多核CPU和多CPU服务器?毕竟,使速度尽可能快的单线程服务器非常好,但是对于高负载,我想使用多个CPU。对于提高应用程序速度也是如此-今天看来,方法是使用多个CPU并使任务并行化。
Node.js如何适合这张图片?它的想法是以某种方式分发多个实例还是什么?
Answers:
Node.js绝对可以在多核计算机上扩展。
是的,Node.js是每个进程一个线程。这是一个非常刻意的设计决策,无需处理锁定语义。如果您不同意这一点,您可能还没有意识到调试多线程代码有多么疯狂。有关Node.js流程模型以及它为何以这种方式起作用的原因(以及为什么它将永远不支持多个线程)的更深入的解释,请阅读我的其他文章。
两种方式:
由于v.6.0.X Node.js 直接包含了群集模块,因此可以轻松设置可以在单个端口上侦听的多个节点工作程序。请注意,这与可通过npm获得的较早的learningboost“集群”模块不同。
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
http.Server(function(req, res) { ... }).listen(8000);
}
工人们将竞争接受新的连接,而负荷最小的过程最有可能获胜。它工作得很好,并且可以在多核设备上很好地扩展吞吐量。
如果您有足够的负载来关心多个内核,那么您将还要做一些其他事情:
在Nginx或Apache之类的Web代理后面运行Node.js服务-可以进行连接限制(除非您希望过载条件完全关闭),重写URL,提供静态内容并代理其他子服务。
定期回收您的工作程序。对于长时间运行的过程,即使是很小的内存泄漏也会最终加起来。
设置日志收集/监控
PS:在另一篇文章的评论中,Aaron和Christopher之间进行了讨论(在撰写本文时,这是其最高文章)。关于此的一些评论:
共享端口: nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)
与
各个端口: nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}
可以说,单个端口设置有一些好处(可能会减少进程之间的耦合,具有更复杂的负载平衡决策等),但是设置绝对是更多的工作,并且内置群集模块的成本很低适用于大多数人的-complexity替代方案。
一种方法是在服务器上运行多个node.js实例,然后在它们前面放置一个负载平衡器(最好是像nginx这样的非阻塞式负载平衡器)。
瑞安·达尔(Ryan Dahl )在去年夏天在Google进行的技术演讲中回答了这个问题。简而言之,“只需运行多个节点进程并使用明智的方法进行通信即可,例如sendmsg()样式的IPC或传统的RPC”。
如果您想立即弄脏手,请查看spark2 Forever模块。它使生成多个节点进程变得异常容易。它负责设置端口共享,因此它们每个都可以接受到同一端口的连接,并且如果要确保进程终止,则还可以自动重生。
您可以使用群集模块。检查一下。
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);
}
多节点可利用您可能拥有的所有核心。
看看http://github.com/kriszyp/multi-node。
为了更简单的需求,您可以在不同的端口号上启动节点的多个副本,并在它们前面放置一个负载均衡器。
Node Js支持群集以充分利用您的cpu。如果您不通过群集运行它,则可能是在浪费硬件功能。
Node.js中的群集允许您创建可以共享同一服务器端口的单独进程。例如,如果我们在端口3000上运行一台HTTP服务器,那么它就是在处理器单核上的单线程上运行的一台服务器。
下面显示的代码使您可以集群应用程序。该代码是由Node.js表示的正式代码。
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
Object.keys(cluster.workers).forEach(function(id) {
console.log("I am running with ID : " + cluster.workers[id].process.pid);
});
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
//Do further processing.
}
在这篇文章中查看完整的教程
我正在使用Node worker从我的主流程以一种简单的方式运行流程。在我们等待正式发布之时,似乎工作做得很好。
您可以通过将集群模块与os模块结合使用来在多个内核上运行node.js应用程序,该模块可用于检测您有多少个CPU。
例如,假设您有一个server
在后端运行简单http服务器的模块,并且想要为多个CPU运行它:
// Dependencies.
const server = require('./lib/server'); // This is our custom server module.
const cluster = require('cluster');
const os = require('os');
// If we're on the master thread start the forks.
if (cluster.isMaster) {
// Fork the process.
for (let i = 0; i < os.cpus().length; i++) {
cluster.fork();
}
} else {
// If we're not on the master thread start the server.
server.init();
}
使用纯TCP负载平衡器(HAProxy)在每个运行一个NodeJS进程的多个框前面可以将NodeJS扩展到多个框。
如果您随后在所有实例之间共享一些常识,则可以使用中央Redis商店或类似商店,然后可以从所有流程实例(例如,从所有包装箱中访问)