Nodejs master + worker模式的多核解决框架——node-cluster
Nodejs master + worker模式的多核解决框架——node-cluster
<p>还在为node运行于单进程而苦恼么?即便是node本身提供了cluster功能,或者在github和npm上有很多优秀的模块帮你做封装,但你仍然逃避不掉这些问题:</p>
<ol> <li>性能问题;</li> <li>多进程worker的存活状态管理;</li> <li>服务的平滑重启;</li> <li>配置或者静态数据的动态reload.</li> </ol>
<p>我相信你完全有能力把这些事情做得很好。但在自己动手之前,为何不尝试一下node-cluster呢? <a href=“https://github.com/aleafs/node-cluster”>https://github.com/aleafs/node-cluster</a></p>
<p>node-cluster只有一个文件,区区500多行代码(包括注释),为你解决了上面的所有问题。利用node-cluster构建你的多进程服务非常简单:</p>
<ol> <li><p>在master进程中,你只需要5行代码:</p>
<blockquote> <pre><code>var cluster = require(‘node-cluster’);
var master = new cluster.Master(); master.register(8080, ‘app.js’); master.dispatch(); </code></pre> </blockquote></li> <li><p>在worker进程中,你只需要关心你的app逻辑即可。一个基于HTTP协议的典型例子如下:</p>
<blockquote> <pre><code>var Http = require(‘http’); var cluster = require(‘node-cluster’);
var admin = new cluster.Worker(); var server = Http.createServer(function (req, res) { admin.transact();
res.writeHead(200, {‘Content-Type’: ‘text/plain;charset=utf-8’}); res.end(‘hello world’);
admin.release(); });
admin.ready(function (socket) { server.emit(‘connection’, socket); }); </code></pre> </blockquote></li> </ol>
<p>实际上,我设计node-cluster的初衷可不只是这点用途。糯米们都能发掘出哪些应用场景呢?</p>
Nodejs Master + Worker 模式的多核解决框架——node-cluster
还在为Node.js运行于单进程而苦恼么?即便是Node.js本身提供了cluster功能,或者在GitHub和npm上有很多优秀的模块帮你做封装,但你仍然逃避不掉这些问题:
- 性能问题;
- 多进程worker的存活状态管理;
- 服务的平滑重启;
- 配置或者静态数据的动态reload。
我相信你完全有能力把这些事情做得很好。但在自己动手之前,为何不尝试一下node-cluster
呢?
node-cluster
只有一个文件,区区500多行代码(包括注释),为你解决了上面的所有问题。利用node-cluster
构建你的多进程服务非常简单:
在Master进程中
你只需要5行代码:
var cluster = require('node-cluster');
var master = new cluster.Master();
master.register(8080, 'app.js');
master.dispatch();
在Worker进程中
你只需要关心你的应用逻辑。以下是一个基于HTTP协议的典型例子:
var http = require('http');
var cluster = require('node-cluster');
var worker = new cluster.Worker();
var server = http.createServer(function (req, res) {
worker.transact();
res.writeHead(200, {'Content-Type': 'text/plain;charset=utf-8'});
res.end('hello world');
worker.release();
});
worker.ready(function (socket) {
server.emit('connection', socket);
});
实际应用
实际上,设计node-cluster
的初衷不仅仅是为了简化多进程管理。通过灵活地使用node-cluster
,你可以实现许多高级应用场景,例如:
- 负载均衡:自动将请求分配到不同的worker进程。
- 故障恢复:自动重启失败的worker进程。
- 动态配置更新:无需重启整个应用即可更新配置。
- 资源监控:实时监控每个worker的资源使用情况。
希望这些示例代码和简要说明能够帮助你快速上手并充分利用node-cluster
的强大功能。如果你有任何疑问或需要进一步的帮助,请随时查看其官方文档或提交issue。
期待性能数据!
在一台超线程可见 5 * Intel® Xeon® CPU E5620 @ 2.40GHz 的虚拟机上用siege2.7本机压测,demo/main.js 下的33749端口,与node原生的http模块进行对比。由于基本不涉及IO操作,保证压测时工作进程CPU吃满,结果如下:
**connection: keep-alive模式下(长连接):siege -b -c2 -t1m **
- 原生HTTP,时长59.76s,QPS:8486.93,请求数507179,可用率100.00%;
- node-cluster,时长59.64s,QPS:8424.51,请求数502438,可用率100.00%;
**connection: close模式下(短连接):siege -b -c1000 **
- 原生HTTP,时长24.15s,QPS:4907.33,请求数118512,可用率99.93%;
- node-cluster,时长20.71s,QPS:3864.61,请求数80036,可用率100.00%;
结论如下:
- 长连接模式下HTTP协议无性能损失。这个容易理解,一旦连接建立,之后的请求就与master无关了;
- 短连接模式下,node-cluster封装之后有20%的QPS损失。在短连接模式下,操作系统的文件句柄数首先达到瓶颈。在测试之前,手工通过ulimit -n调整 max opend files为65535,并且在TIME_WAIT状态的TCP连接数小于100的情况下开始压测。
- 普遍而言,node的HTTP模块在短连接模式下,比长连接有接近50%的QPS损失。这一点要根据node的使用场景来判断用那种模式。在node做中间层服务时,我们建议采用keep-alive方式。
话说虚拟机真弱啊,在我的mac上,上边的测试,轻轻松松抛出两倍的QPS
mac上的文件句柄数设置搞掂了?
admin. transact()
和 admin.release()
要使用者自行判断在那里调用?这样的使用体验不好啊。
应该让用户对这些没感觉才好,让他们使用起来就像普通的处理逻辑一样。
大概搞掂了,用的zsh,ulimit -n 就可以
要是不想要平滑重启,能容忍少量的请求丢失,那么不要调这两个方法也可以
我想问下,多进程内存共享后台有自动同步吗?比如我想同步一些json数据,但是又不想借助如redis,mongodb等的第三方缓存。
没啥意义
木有的,数据量大的话我还是建议用这些东西共享
master.register(8080, ‘app.js’); 我想添加的是unix socket file,这个能做到吗,就是结合socket和node-cluster
node -v给我瞧瞧
你好,我想问一下,通过child_process.fork()出来的子进程及该进程下的线程,如何保证是在不同的CPU核上运行的?
这个是由系统调用平均分配的吗?
node进程里应该保证不了。一般情况是有系统负责的。也可以在外部通过taskset来绑定CPU
你好,你的node-cluster地址坏了。求代码
[worker:6591][Tue Nov 19 2013 16:59:36 GMT+0800 (CST)] Error: EPERM, Operation not permitted, ignore,我在linux下遇到这个错误,node版本是0.10.13,是什么原因呢?
权限
mark
mark 自豪地采用 CNodeJS ionic
Node.js 的 node-cluster
模块提供了一种简单的 Master 和 Worker 模式来充分利用多核 CPU,解决性能、多进程存活状态管理、服务平滑重启及配置动态 reload 等问题。以下是使用该模块的基本示例代码:
Master 进程
// 在master进程中
var cluster = require('node-cluster');
var master = new cluster.Master();
master.register(8080, 'app.js');
master.dispatch();
这段代码创建了一个 Master 实例,并注册了一个监听端口为 8080 的 app.js 工作进程。dispatch()
方法则启动了 master 和 worker 之间的通信。
Worker 进程
// 在worker进程中
var Http = require('http');
var cluster = require('node-cluster');
var admin = new cluster.Worker();
var server = Http.createServer(function (req, res) {
admin.transact();
res.writeHead(200, {'Content-Type': 'text/plain;charset=utf-8'});
res.end('hello world');
admin.release();
});
admin.ready(function (socket) {
server.emit('connection', socket);
});
这段代码设置了一个 HTTP 服务器,用于处理请求并返回 “hello world”。通过调用 admin.transact()
和 admin.release()
来控制 worker 进程的任务调度与资源释放。
解释
- Master 进程 负责启动和管理多个 Worker 进程,实现负载均衡。
- Worker 进程 则专注于业务逻辑的处理,当需要进行任务调度时,可以通过
transact()
方法通知 master 进程。 - 通过这样的架构,可以有效利用多核 CPU 提升应用性能,同时简化了进程管理和状态监控的工作。
node-cluster
模块的简洁性使其成为一个快速搭建高性能 Node.js 应用的不错选择。