Node.js看起来很有趣,但我必须错过一些东西 - 不是Node.js只调整为在单个进程和线程上运行吗?
那么它如何扩展多核CPU和多CPU服务器?毕竟,尽可能快速地制作单线程服务器,但是对于高负载我想要使用多个CPU.同样可以使应用程序更快 - 似乎今天的方式是使用多个CPU并并行化任务.
Node.js如何适应这张图片?它的想法是以某种方式分发多个实例或什么?
Node.js绝对可以在多核机器上进行扩展.
是的,Node.js是每个进程一个线程.这是一个非常慎重的设计决策,无需处理锁定语义.如果您不同意这一点,您可能还没有意识到调试多线程代码是多么的难以理解.有关Node.js流程模型的更深入解释以及为什么它以这种方式工作(以及为什么它永远不会支持多个线程),请阅读我的其他帖子.
两种方式:
对于像图像编码这样的大型计算任务,Node.js可以启动子进程或向其他工作进程发送消息.在这个设计中,你有一个线程来管理事件流和N个进程执行繁重的计算任务并咀嚼其他15个CPU.
为了在Web服务上扩展吞吐量,您应该在一个盒子上运行多个Node.js服务器,每个核心一个,并在它们之间分割请求流量.这提供了出色的CPU亲和力,并且可以随着核心数量几乎线性地扩展吞吐量.
由于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); }
工人将竞争接受新的联系,最少负担的过程最有可能获胜.它运行良好,可以在多核盒上很好地扩大吞吐量.
如果你有足够的负载来关心多个核心,那么你也想要做更多的事情:
在像Nginx或Apache这样的Web代理后面运行Node.js服务- 可以进行连接限制(除非您希望过载条件完全关闭框),重写URL,提供静态内容以及代理其他子服务.
定期回收您的工作进程.对于长时间运行的进程,即使很小的内存泄漏最终也会增加.
设置日志收集/监视
PS:Aaron和Christopher在另一篇文章的评论中进行了讨论(截至本文撰写时,它是最高职位).对此有一些评论:
共享套接字模型非常便于允许多个进程侦听单个端口并竞争接受新连接.从概念上讲,你可以想到preforked Apache这样做的重要警告是每个进程只接受一个连接然后死掉.Apache的效率损失是分支新进程的开销,与套接字操作无关.
对于Node.js,让N个工作者在单个套接字上竞争是一个非常合理的解决方案.另一种方法是建立一个像Nginx这样的机上前端,并为每个工作人员提供代理流量,在工作人员之间交替分配新连接.这两种解决方案具有非常相似的性能特征 因为,正如我上面提到的,你可能想要让Nginx(或替代方案)面向你的节点服务,这里的选择实际上是:
共享端口: nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)
VS
个人港口: nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}
对于各个端口设置可能有一些好处(可能在进程之间具有较少的耦合,具有更复杂的负载平衡决策等),但是设置肯定更多工作并且内置集群模块是低的 - 适用于大多数人的复杂替代品.
一种方法是在服务器上运行node.js的多个实例,然后在它们前面放置一个负载均衡器(最好是非阻塞的,如nginx).
Ryan Dahl 在去年夏天他在Google上发表的技术讲话中回答了这个问题.换言之,"只需运行多个节点进程并使用合理的东西来允许它们进行通信.例如sendmsg() - 样式IPC或传统的RPC".
如果您想立即弄脏手,请查看spark2 Forever模块.它使得生成多个节点进程变得非常简单.它处理设置端口共享,因此它们每个都可以接受到同一端口的连接,并且如果要确保进程在其停止时重新启动,也会自动重新生成.
更新 - 10/11/11:节点社区中的共识似乎是Cluster现在是每台机器管理多个节点实例的首选模块. 永远值得一看.
您可以使用群集模块.检查一下.
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.
对于更简单的需求,您可以在不同的端口号上启动多个节点副本,并在其前面放置负载均衡器.
如上所述,Cluster将跨所有核心扩展和负载均衡您的应用.
添加类似的东西
cluster.on('exit', function () { cluster.fork(); });
将重启任何失败的工人.
如今,很多人也更喜欢PM2,它可以为您处理集群,并提供一些很酷的监控功能.
然后,在运行集群的多台计算机前添加Nginx或HAProxy,您可以实现多级故障转移和更高的负载容量.
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. }
查看本文以获取完整教程
节点的未来版本将允许您创建一个进程,并传递消息给它和瑞安曾表示,他希望找到某种方式也分享文件处理程序,所以它不会是一个简单的Web工作落实.
目前还没有一个简单的解决方案,但它仍然很早,节点是我见过的最快速移动的开源项目之一,所以期待在不久的将来有一些很棒的东西.
Spark2基于Spark,现在不再维护.Cluster是它的继承者,它有一些很酷的功能,比如每个CPU核心产生一个工作进程并重新生成死亡工人.
我正在使用Node worker以一种简单的方式从我的主进程运行进程.当我们等待正式的出路时,似乎工作得很好.
这里的新孩子是LearnBoost的"Up".
它提供"零停机重新加载",并另外创建多个工作程序(默认情况下,CPU的数量,但它是可配置的),以提供所有世界中最好的.
它是新的,但似乎非常稳定,我在我目前的一个项目中愉快地使用它.