使用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分页效果示例
Oct 11 Javascript
JS获取IP、MAC和主机名的五种方法
Nov 14 Javascript
JavaScript插件化开发教程(六)
Feb 01 Javascript
基于jquery实现的自动补全功能
Mar 12 Javascript
jquery图片滚动放大代码分享(1)
Aug 25 Javascript
JS与jQuery遍历Table所有单元格内容的方法
Dec 07 Javascript
使用Node.js处理前端代码文件的编码问题
Feb 16 Javascript
javascript的BOM
May 03 Javascript
Yarn的安装与使用详细介绍
Oct 25 Javascript
AngularJS入门教程之过滤器用法示例
Nov 02 Javascript
jquery中$.fn和图片滚动效果实现的必备知识总结
Apr 21 jQuery
vue中全局路由守卫中替代this操作(this.$store/this.$vux)
Jul 24 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函数实现数字与文字分页代码
2015/07/28 PHP
jQuery maxlength文本字数限制插件
2010/04/16 Javascript
Extjs实现进度条的两种便捷方式
2013/09/26 Javascript
Array栈方法和队列方法的特点说明
2014/01/24 Javascript
javascript 获取元素样式必杀技
2014/05/04 Javascript
jQuery实现Twitter的自动文字补齐特效
2014/11/28 Javascript
教你使用javascript简单写一个页面模板引擎
2015/05/05 Javascript
js实现表单检测及表单提示的方法
2015/08/14 Javascript
基于JavaScript实现复选框的全选和取消全选
2017/02/09 Javascript
基于vue实现分页/翻页组件paginator示例
2017/03/09 Javascript
vue货币过滤器的实现方法
2017/04/01 Javascript
JS 组件系列之BootstrapTable的treegrid功能
2017/06/16 Javascript
vue-resource 拦截器(interceptor)的使用详解
2017/07/04 Javascript
Vue单文件组件的如何使用方式介绍
2017/07/28 Javascript
写gulp遇到的ES6问题详解
2018/12/03 Javascript
js实现无缝轮播图
2020/03/09 Javascript
vue使用video插件vue-video-player详解
2020/10/23 Javascript
简单掌握Python的Collections模块中counter结构的用法
2016/07/07 Python
详解关于Django中ORM数据库迁移的配置
2018/10/08 Python
浅谈python中真正关闭socket的方法
2018/12/18 Python
python正则表达式匹配[]中间为任意字符的实例
2018/12/25 Python
django使用django-apscheduler 实现定时任务的例子
2019/07/20 Python
解决pycharm最左侧Tool Buttons显示不全的问题
2019/12/17 Python
CSS3实现可关闭的下拉手风琴菜单效果
2015/08/31 HTML / CSS
移动端html5 meta标签的神奇功效
2016/01/06 HTML / CSS
html5.2 dialog简介详解
2018/02/27 HTML / CSS
英国护发和美妆在线商店:Klip Shop
2019/03/24 全球购物
英国家具、照明、家居用品网上商店:Wayfair.co.uk
2020/02/13 全球购物
护士自我介绍信
2014/01/13 职场文书
学位证书委托书
2014/09/30 职场文书
优秀党务工作者先进事迹材料
2014/12/25 职场文书
运动会入场词
2015/07/18 职场文书
《钢铁是怎样炼成的》高中读后感
2019/08/07 职场文书
创业分两种人:那么哪些适合创业?,哪些适合不适合创业呢?
2019/08/23 职场文书
星际争霸 Light vs Action 一场把教主看到鬼畜的比赛
2022/04/01 星际争霸
SpringBoot 集成短信和邮件 以阿里云短信服务为例
2022/04/22 Java/Android