用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
"); }).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 }) }