使用cluster 将自己的Node服务器扩展为多线程服务器


Posted in Javascript onNovember 10, 2014

用nodejs的朋友都有了解,node是单线程的,也就是说跑在8核CPU上,只能使用一个核的算力。
单线程一直是node的一个诟病,但随着0.6版本中引入cluster之后,这个情况则得到了改变,开发人员可以依靠cluster很轻松的将自己的Node服务器扩展为多线程服务器了。

什么是Cluster

cluster是node提供的一个多线程库,用户可以使用它来创建多个线程,线程之间共享一个监听端口,当有外部请求这个端口时,cluster会将请求转发到随机线程里。因为每个node线程都会占用几十兆的内存,所以不能像php那样对每个请求创建一个线程,一般来说创建的线程数最多都不会超过cpu的核心数量。

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);

}

如以上代码所示,程序运行时cluster.isMaster会被设置为true,当调用cluster.fork()之后,程序会创建一个线程,并重新运行,这时cluster.isMaster就被设置为false了。我们就主要通过这个变量来判断当前线程是不是子线程的。

还可以注意到,每个子线程被创建之后,都会监听8000端口而不会引起冲突,这就是cluster共享端口的功能了。

线程之间的通信

当线程被创建之后,他们彼此之间是没有共享内存或者数据的。所有的数据交换只能通过worker.send和worker.on('message',handler)在主线程里处理,下面列举一个广播系统的实例。

var cluster = require('cluster');

var http = require('http');

var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
  var workers=[];

  //新建worker

  function newWorker(){

    var worker=cluster.fork();
    //监听信息,如果type为broadcast的话,则确定为广播

    worker.on('message', function(msg) {

      if(msg.type=='broadcast'){

        var event=msg.event;

        //向所有worker发送此条广播

        workers.forEach(function(worker){

          worker.send(event);

        })

      }

    });

    return worker;

  }
  for (var i = 0; i < numCPUs; i++) {

    workers.push(newWorker());

  }
    cluster.on('online',function(worker){

        console.log('worker %d is online',worker.id);

    })

} else {

  var worker=cluster.worker;
  //广播就是发送一个type为broadcast的信息,event就是广播内容

  worker.broadcast=function(event){

    worker.send({

      type:'broadcast',

      event:event

    });

  }
  //这里用worker.on貌似不能监听到返回的信息

  process.on('message',function(event){

    console.log('worker: '+worker.id+' recived event from '+event.workerId);

  })
  //发送广播

  worker.broadcast({

    message:'online',

    workerId:worker.id

  })

}

需要注意的问题

在上面也提到,线程之间是不能共享数据的,所有的数据交换只能通过线程之间的通信来交换。而且所交换的数据都是可序列化的,所以函数,文件描述符和HttpResponse之类的东西都不能传递。

如果使用cluster,则需要在程序设计的时候考虑到数据交换的问题,我自己的做法就是将类似session的这些数据都存放在redis里,每个线程都做好存取的工作,所有的数据都不放在node内存里。

最后一点,cluster目前还被Node官方标记为Experimental状态,api在将来也许会改变。

Javascript 相关文章推荐
一个网马的tips实现分析
Nov 28 Javascript
jQuery中操控hidden、disable等无值属性的方法
Jan 06 Javascript
jquery插件开发之实现google+圈子选择功能
Mar 10 Javascript
5个最顶级jQuery图表类库插件【jquery插件库】
May 05 Javascript
AngularJS表单验证中级篇(3)
Sep 28 Javascript
JS实现图片点击后出现模态框效果
May 03 Javascript
最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等
Aug 16 Javascript
VueJs监听window.resize方法示例
Jan 17 Javascript
微信小程序 scroll-view 水平滚动实现过程解析
Oct 12 Javascript
Vue-cli3项目引入Typescript的实现方法
Oct 18 Javascript
three.js利用卷积法如何实现物体描边效果
Nov 27 Javascript
JS倒计时两种实现方式代码实例
Jul 27 Javascript
前端必备神器 Snap.svg 弹动效果
Nov 10 #Javascript
浅谈JavaScript 框架分类
Nov 10 #Javascript
使用script的src实现跨域和类似ajax效果
Nov 10 #Javascript
jquery插件推荐 jquery.cookie
Nov 09 #Javascript
jquery插件推荐浏览器嗅探userAgent
Nov 09 #Javascript
Javascript限制网页只能在微信内置浏览器中访问
Nov 09 #Javascript
js闭包的用途详解
Nov 09 #Javascript
You might like
彻底杜绝PHP的session cookie错误
2009/08/09 PHP
基于curl数据采集之正则处理函数get_matches的使用
2013/04/28 PHP
解析php中用PHPMailer来发送邮件的示例(126.com的例子)
2013/06/24 PHP
使用WAMP搭建PHP本地开发环境
2017/05/10 PHP
javascript 添加和移除函数的通用方法
2009/10/20 Javascript
基于jQuery的获得各种控件Value的方法
2010/11/19 Javascript
JS数组的赋值介绍
2014/03/10 Javascript
JS将光标聚焦在文本最后的实现代码
2014/03/28 Javascript
利用jQuery实现可以编辑的表格
2014/05/26 Javascript
JS遍历Json字符串中键值对先转成JSON对象再遍历
2014/08/15 Javascript
JavaScript实现同步于本地时间的动态时间显示方法
2015/02/02 Javascript
JavaScript创建一个object对象并操作对象属性的用法
2015/03/23 Javascript
javascript实现完美拖拽效果
2015/05/06 Javascript
Node.JS使用Sequelize操作MySQL的示例代码
2017/10/09 Javascript
JavaScript常用数学函数用法示例
2018/05/14 Javascript
详解性能更优越的小程序图片懒加载方式
2018/07/18 Javascript
jQuery实现的鼠标拖动浮层功能示例【拖动div等任何标签】
2018/12/29 jQuery
微信小程序学习笔记之登录API与获取用户信息操作图文详解
2019/03/29 Javascript
vue data恢复初始化数据的实现方法
2019/10/31 Javascript
python中将字典转换成其json字符串
2014/07/16 Python
浅析Python的Django框架中的Memcached
2015/07/23 Python
Python实现调用另一个路径下py文件中的函数方法总结
2018/06/07 Python
Django安装配置mysql的方法步骤
2018/10/15 Python
Pycharm2017版本设置启动时默认自动打开项目的方法
2018/10/29 Python
基于Python的OCR实现示例
2020/04/03 Python
美国学校用品、教室和教学商店:Discount School Supply
2018/04/04 全球购物
女士鞋子、包包和服装在线,第一款10美元:ShoeDazzle
2019/07/26 全球购物
Servlet如何得到服务器的信息
2015/12/22 面试题
药剂学专业应届生自荐信
2013/09/29 职场文书
工程专业求职自荐书范文
2014/02/18 职场文书
禁毒宣传工作方案
2014/05/23 职场文书
信息管理专业自荐书
2014/06/05 职场文书
保护校园环境倡议书
2015/04/28 职场文书
MySQL中你可能忽略的COLLATION实例详解
2021/05/12 MySQL
Mysql数据库命令大全
2021/05/26 MySQL
MySQL不使用order by实现排名的三种思路总结
2021/06/02 MySQL