发布时间:2022-08-09 文章分类:编程知识 投稿人:王小丽 字号: 默认 | | 超大 打印

master + worker模式的node多核解决框架——node-cluster

还在为node运行于单进程而苦恼么?即便是node本身提供了cluster功能,或者在github和npm上有很多优秀的模块帮你做封装,但你仍然逃避不掉这些问题:

  1. 性能问题;
  2. 多进程worker的存活状态管理;
  3. 服务的平滑重启;
  4. 配置或者静态数据的动态reload.

我相信你完全有能力把这些事情做得很好。但在自己动手之前,为何不尝试一下node-cluster呢?
https://github.com/aleafs/node-cluster

node-cluster只有一个文件,区区500多行代码(包括注释),为你解决了上面的所有问题。利用node-cluster构建你的多进程服务非常简单:

  1. 在master进程中,你只需要5行代码:

    var cluster =require('node-cluster');var master =new cluster.Master();
    master.register(8080,'app.js');
    master.dispatch();
  2. 在worker进程中,你只需要关心你的app逻辑即可。一个基于HTTP协议的典型例子如下:

    varHttp=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);});

实际上,我设计node-cluster的初衷可不只是这点用途。糯米们都能发掘出哪些应用场景呢?

标签:


原创文章


pengchun 在 2012-2-1 21:13发布


pengchun 在 2012-2-2 10:22重新编辑

分享到 weibo

8 回复

#1
kongwu

期待性能数据!


kongwu 在 2012-2-2 00:42回复

#2
pengchun

在一台超线程可见 5 * Intel(R) Xeon(R) CPU E5620 @ 2.40GHz 的虚拟机上用siege2.7本机压测,demo/main.js 下的33749端口,与node原生的http模块进行对比。由于基本不涉及IO操作,保证压测时工作进程CPU吃满,结果如下:

*connection: keep-alive模式下(长连接):siege -b -c2 -t1m *

  1. 原生HTTP,时长59.76s,QPS:8486.93,请求数507179,可用率100.00%;
  2. node-cluster,时长59.64s,QPS:8424.51,请求数502438,可用率100.00%;

*connection: close模式下(短连接):siege -b -c1000 *

  1. 原生HTTP,时长24.15s,QPS:4907.33,请求数118512,可用率99.93%;
  2. node-cluster,时长20.71s,QPS:3864.61,请求数80036,可用率100.00%;

结论如下:

  1. 长连接模式下HTTP协议无性能损失。这个容易理解,一旦连接建立,之后的请求就与master无关了;

  2. 短连接模式下,node-cluster封装之后有20%的QPS损失。在短连接模式下,操作系统的文件句柄数首先达到瓶颈。在测试之前,手工通过ulimit -n调整 max opend files为65535,并且在TIME_WAIT状态的TCP连接数小于100的情况下开始压测。

  3. 普遍而言,node的HTTP模块在短连接模式下,比长连接有接近50%的QPS损失。这一点要根据node的使用场景来判断用那种模式。在node做中间层服务时,我们建议采用keep-alive方式。


pengchun 在 2012-2-2 08:13回复

#3
pengchun

话说虚拟机真弱啊,在我的mac上,上边的测试,轻轻松松抛出两倍的QPS


pengchun 在 2012-2-2 09:13回复

{2}

suqian

mac上的文件句柄数设置搞掂了?


suqian 在 2012-2-2 10:00回复

pengchun

大概搞掂了,用的zsh,ulimit -n 就可以


pengchun 在 2012-2-2 10:23回复

#4
suqian

admin. transact()admin.release() 要使用者自行判断在那里调用?这样的使用体验不好啊。

应该让用户对这些没感觉才好,让他们使用起来就像普通的处理逻辑一样。


suqian 在 2012-2-2 10:13回复

{1}

pengchun

要是不想要平滑重启,能容忍少量的请求丢失,那么不要调这两个方法也可以


pengchun 在 2012-2-2 10:24回复

#5
suqian

@pengchun

function listenAt(obj, port){var server  =new TCP();
  server.bind('0.0.0.0', port);
  server.listen('/dev/null');

server.listen('/dev/null'); 有具体含义吗?


suqian 在 2012-2-13 17:42回复

{1}

pengchun

没啥意义


pengchun 在 2012-2-15 10:17回复

#6
fish

@pengchun 同求解 :)


fish 在 2012-2-13 22:54回复

#7
snoopy

我想问下,多进程内存共享后台有自动同步吗?比如我想同步一些json数据,但是又不想借助如redis,mongodb等的第三方缓存。


snoopy 在 2012-2-14 10:23回复

{1}

pengchun

木有的,数据量大的话我还是建议用这些东西共享


pengchun 在 2012-2-15 10:18回复

#8
mackjoner

master.register(8080, 'app.js');
我想添加的是unix socket file,这个能做到吗,就是结合socket和node-cluster

var cluster =require('node-cluster');var master =new cluster.Master();
master.register(8080,'app.js');
master.dispatch();
varHttp=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);});

*connection: keep-alive模式下(长连接):siege -b -c2 -t1m *

  1. 原生HTTP,时长59.76s,QPS:8486.93,请求数507179,可用率100.00%;
  2. node-cluster,时长59.64s,QPS:8424.51,请求数502438,可用率100.00%;

*connection: close模式下(短连接):siege -b -c1000 *

  1. 原生HTTP,时长24.15s,QPS:4907.33,请求数118512,可用率99.93%;
  2. node-cluster,时长20.71s,QPS:3864.61,请求数80036,可用率100.00%;
  1. 长连接模式下HTTP协议无性能损失。这个容易理解,一旦连接建立,之后的请求就与master无关了;

  2. 短连接模式下,node-cluster封装之后有20%的QPS损失。在短连接模式下,操作系统的文件句柄数首先达到瓶颈。在测试之前,手工通过ulimit -n调整 max opend files为65535,并且在TIME_WAIT状态的TCP连接数小于100的情况下开始压测。

  3. 普遍而言,node的HTTP模块在短连接模式下,比长连接有接近50%的QPS损失。这一点要根据node的使用场景来判断用那种模式。在node做中间层服务时,我们建议采用keep-alive方式。