使用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 相关文章推荐
defer属性导致引用JQuery的页面报“浏览器无法打开网站xxx,操作被中止”错误的解决方法
Apr 27 Javascript
javascript动态添加样式(行内式/嵌入式/外链式等规则)
Jun 24 Javascript
Jquery右下角抖动、浮动 实例代码(兼容ie6、FF)
Aug 15 Javascript
cookie中的path与domain属性详解
Dec 18 Javascript
Windows 系统下安装和部署Egret的开发环境
Jul 31 Javascript
Angularjs使用ng-repeat中$even和$odd属性的注意事项
Dec 31 Javascript
EasyUI实现下拉框多选功能
Nov 07 Javascript
JS+HTML+CSS实现轮播效果
Nov 28 Javascript
基于vue v-for 多层循环嵌套获取行数的方法
Sep 26 Javascript
为什么要使用Vuex的介绍
Jan 19 Javascript
一步快速解决微信小程序中textarea层级太高遮挡其他组件
Mar 04 Javascript
详解JS浏览器事件循环机制
Mar 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基础知识:类与对象(1)
2006/12/13 PHP
学习php设计模式 php实现装饰器模式(decorator)
2015/12/07 PHP
php ajax数据传输和响应方法
2018/08/21 PHP
Laravel框架集合用法实例浅析
2020/05/14 PHP
PHP后门隐藏的一些技巧总结
2020/11/04 PHP
FileUpload 控件 禁止手动输入或粘贴的实现代码
2010/04/07 Javascript
input 和 textarea 输入框最大文字限制的jquery插件
2011/10/27 Javascript
JS编程小常识很有用
2012/11/26 Javascript
JavaScript检测并限制复选框选中个数的方法
2015/08/12 Javascript
jquery实现红色竖向多级向右展开的导航菜单效果
2015/08/31 Javascript
js利用正则表达式检验输入内容是否为网址
2016/07/05 Javascript
使用JavaScript判断用户输入的是否为正整数(两种方法)
2017/02/05 Javascript
基于Bootstrap 3 JQuery及RegExp的表单验证功能
2017/02/16 Javascript
利用Ionic2 + angular4实现一个地区选择组件
2017/07/27 Javascript
vue.js-div滚动条隐藏但有滚动效果的实现方法
2018/03/03 Javascript
koa2 从入门到精通(小结)
2019/07/23 Javascript
JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解
2019/08/16 Javascript
[01:20]DOTA2上海特级锦标赛现场采访:谁的ID最受青睐
2016/03/25 DOTA
从零学python系列之数据处理编程实例(一)
2014/05/22 Python
CentOS 6.X系统下升级Python2.6到Python2.7 的方法
2016/10/12 Python
Python使用min、max函数查找二维数据矩阵中最小、最大值的方法
2018/05/15 Python
python批量创建指定名称的文件夹
2019/03/21 Python
python使用pip安装模块出现ReadTimeoutError: HTTPSConnectionPool的解决方法
2019/10/04 Python
python3中pip3安装出错,找不到SSL的解决方式
2019/12/12 Python
Python实现大数据收集至excel的思路详解
2020/01/03 Python
python3实现raspberry pi(树莓派)4驱小车控制程序
2020/02/12 Python
Python实现自动签到脚本功能
2020/08/20 Python
python 实现图片裁剪小工具
2021/02/02 Python
怎样实现H5+CSS3手指滑动切换图片的示例代码
2019/05/05 HTML / CSS
C/C++ 笔试、面试题目大汇总
2015/11/21 面试题
五好家庭申报材料
2014/12/20 职场文书
文明倡议书
2015/01/19 职场文书
开学第一天的感想
2015/08/10 职场文书
优秀党员主要事迹材料
2015/11/04 职场文书
PHP新手指南
2021/04/01 PHP
python超详细实现完整学生成绩管理系统
2022/03/17 Python