使用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 相关文章推荐
js Function类型
Dec 04 Javascript
用jquery实现的一个超级简单的下拉菜单
May 18 Javascript
javascript弹出页面回传值的方法
Jan 28 Javascript
举例详解Python中smtplib模块处理电子邮件的使用
Jun 24 Javascript
js验证真实姓名与身份证号是否匹配
Oct 13 Javascript
JavaScript学习笔记之数组去重
Mar 23 Javascript
JavaScript中误用/g导致的正则test()无法正确重复执行的解决方案
Jul 27 Javascript
php 修改密码实现代码
May 24 Javascript
jQuery UI Draggable + Sortable 结合使用(实例讲解)
Sep 07 jQuery
vue实现固定位置显示功能
May 30 Javascript
详解Webpack抽离第三方类库以及common解决方案
Mar 30 Javascript
javascript实现时钟动画
Dec 03 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脚本数据库功能详解(上)
2006/10/09 PHP
连接到txt文本的超链接,不直接打开而是点击后下载的处理方法
2009/07/01 PHP
JS中encodeURIComponent函数用php解码的代码
2012/03/01 PHP
深入解析PHP中逗号与点号的区别
2013/08/05 PHP
CI框架中通过hook的方式实现简单的权限控制
2015/01/07 PHP
php_pdo 预处理语句详解
2016/11/21 PHP
Laravel validate error处理,ajax,json示例
2019/10/25 PHP
百度Popup.js弹出框进化版 拖拽小框架发布 兼容IE6/7/8,Firefox,Chrome
2010/04/13 Javascript
关于javascript function对象那些迷惑分析
2011/10/24 Javascript
js修改input的type属性及浏览器兼容问题探讨与解决
2013/01/23 Javascript
Javascript单元测试框架QUnitjs详细介绍
2014/05/08 Javascript
JQuery页面地址处理插件jqURL详解
2015/05/03 Javascript
Bootstrap布局组件教程之Bootstrap下拉菜单
2016/06/12 Javascript
微信公众平台开发教程(五)详解自定义菜单
2016/12/02 Javascript
jQuery实现删除li节点的方法
2016/12/06 Javascript
ES6使用let命令更简单的实现块级作用域实例分析
2017/03/31 Javascript
NodeJS有难度的面试题(能答对几个)
2019/10/09 NodeJs
vue的webcamjs集成方式
2020/11/16 Javascript
[00:32]2018DOTA2亚洲邀请赛EG出场
2018/04/03 DOTA
[03:24][TI9纪实] Dota奶爸
2019/08/22 DOTA
Python在Windows和在Linux下调用动态链接库的教程
2015/08/18 Python
深入理解Python中的内置常量
2017/05/20 Python
python使用super()出现错误解决办法
2017/08/14 Python
python中通过预先编译正则表达式提高效率
2017/09/25 Python
python 动态加载的实现方法
2017/12/22 Python
Python3中详解fabfile的编写
2018/06/24 Python
python利用Opencv实现人脸识别功能
2019/04/25 Python
python Elasticsearch索引建立和数据的上传详解
2019/08/04 Python
python带参数打包exe及调用方式
2019/12/21 Python
使用python实现希尔、计数、基数基础排序的代码
2019/12/25 Python
基于Python的OCR实现示例
2020/04/03 Python
canvas实现漂亮的下雨效果的示例
2018/04/18 HTML / CSS
LACOSTE波兰官网:Polo衫、服装和鞋类
2020/09/29 全球购物
内容编辑个人求职信
2013/12/10 职场文书
清明节文明祭祀倡议书
2015/04/28 职场文书
Python中的np.argmin()和np.argmax()函数用法
2021/06/02 Python