node性能提升,有关Cluset模块

单个node实例运行在单线程中,要发挥多核系统的能力,用户有时候需要启动一个node进程集群来处理负载。

集群(cluseter)模块,允许你方便的创建一个共享服务器端口的进程网络。

代码如下:

var http = require("http");
var cluster = require('cluster');
var os = require('os');
var numCPUs = os.cpus().length;// 获取CPU 的数量,其实是核的个数,因为好多cpu都是多核的
var workers = {};//一个存储活动工作进程对象的哈希表,以id字段为主键。它能被用作遍历所有工作进程,仅在主进程中可用

// 遍历所有工作进程
function eachWorker(callback) {
  for (var id in cluster.workers) {
    callback(cluster.workers[id]);
  }
}
eachWorker(function(worker) {
  worker.send('向一线工作者们致以亲切问候!');
});

if (cluster.isMaster){//如果是主进程则啥都不干,只负责创建新的进程(数量与cpu数量一样)
cluster.on('death', function (worker) {//注册集群的死亡事件,当一个进程死亡的时候调用[删除死亡进程,并重新fork一个添加到队列]
// 当一个工作进程结束时,重启工作进程
console.log("one workThread death ,restart another");
delete workers[worker.pid];
worker = cluster.fork();//返回子进程的process对象需要使用:cluster.fork().process
workers[worker.pid] = worker;
}
  );
// 初始开启与CPU 数量相同的工作进程
for (var i = 0; i < numCPUs; i++) {
var worker = cluster.fork();//创建worker进程,返回子进程的process对象需要使用:cluster.fork().process
workers[worker.pid] = worker;
}
}else if(cluster.isWorker){//如果不是主进程,则进行真正的业务处理【启动服务器,并返回结果】
// 工作进程分支,启动服务器
console.log("[worker]  start worker ..." + cluster.worker.id);
var app =  http.createServer(function (req, res) {
        console.log('worker'+cluster.worker.id);//cluster.worker获得当前的worker对象 
        res.end('worker'+cluster.worker.id+',PID:'+process.pid+"    ok");
      }).listen(3000);
}
// 当主进程被终止时,关闭所有工作进程
process.on('SIGTERM', function () {
console.log('mainThread  sigterm!!');
for (var pid in workers) {
process.kill(pid);
}
process.exit(0);}
);


将上面的代码保存为cluster.js文件,然后在node环境去执行: node cluster.js

结果发现:windows不能生效

而linux可以顺利执行


后来在node的开发api中查询到原因,地址是:http://nodeapi.ucdok.com/#/api/cluster.html





-==============================================================

继续来点后话:在后续的开发中遇到点问题:

我们linux服务器是双cpu四核,所以一共能起8个进程,也就是上面的os.cpus().length

我的需求是要接受请求,进而来收集请求的数据写文件:

考虑到多线程,所以我就想着这样的话好需要自己来控制,每个进程(也就每个核)要独立的去写属于自己核操作的文件:

于是就自己为每个核去写计数器什么的,很辛苦的,结果。。。。结果。。。。结果。。。。结果是:不需要自己写

node的这种机制本身就是单线程,每个请求接受的处理都是独立的。


代码如下:

//*********************************************************

var http = require("http");
var url=require("url");
var querystring=require("querystring");
var cluster = require('cluster');
var os = require('os');
var fs = require('fs');
var numCPUs = os.cpus().length;// 获取CPU 的数量
var workers = {};


console.log('numCPUs=' + numCPUs);


console.log('cluster.isMaster=' + cluster.isMaster);


if (cluster.isMaster){
console.log('mainThread!');
// 主进程分支
cluster.on('death', function (worker) {
// 当一个工作进程结束时,重启工作进程
console.log("one workThread death ,restart another");
delete workers[worker.pid];
worker = cluster.fork();//返回子进程的process对象需要使用:cluster.fork().process
workers[worker.pid] = worker;
}
  );
// 初始开启与CPU 数量相同的工作进程
for (var i = 0; i < numCPUs; i++) {
var worker = cluster.fork();//创建worker进程,返回子进程的process对象需要使用:cluster.fork().process
workers[worker.pid] = worker;

}



}else if(cluster.isWorker){
var core_counters = 0;//先定义每个core接受的请求的多个计数器
var core_counters_all = 0;//先定义每个core接受的请求总共请求个数的计数器
var files = '';//每个core的文件内容
var fileNums = 0;//每个核心写文件的个数
console.log("cluster.worker.id = "+cluster.worker.id);



// 工作进程分支,启动服务器
   //http://localhost:3000?appId=736963&userId=1349387&funId=1001&funNum=2345&clientType=Firefox&clientVersion=3.20.12
   http.createServer(function(request,response){
console.log("Request received.  "+'worker'+cluster.worker.id);//cluster.worker获得当前的worker对象 ,从1开始计数


  var pathname = url.parse(request.url).pathname;  //pathname => select
      var arg = url.parse(request.url).query;     //arg => name=a&id=5
      var appId = querystring.parse(arg).appId;         
      var userId = querystring.parse(arg).userId;         
      var funId = querystring.parse(arg).funId;         
      var funNum = querystring.parse(arg).funNum;        
      var clientType = querystring.parse(arg).clientType;         //clientType => Firefox  浏览器类型
      var clientVersion = querystring.parse(arg).clientVersion;         //clientVersion => 10.23.5  浏览器版本
      core_counters++;
      core_counters_all++;
      files += appId+"\t"+userId+"\t"+funId+"\t"+funNum+"\t"+clientType+"\t"+clientVersion+"\n";
      
      
      
    console.log(core_counters);
    console.log(core_counters_all);
  if(core_counters>0&&(core_counters%100==0)){//每有100个请求,准备到内存中去写一次    //如果还没有攒够,就先在内存中加
  console.log("ready to write!!!");
  response.writeHead(200, {"Content-Type": "text/plain"});
  
  var fileName = "core"+(parseInt(cluster.worker.id))+"_"+fileNums+".text";
  
  if(core_counters_all<300){//如果现有文件,没有超过300条则在旧文件基础上追加
  console.log("append to file !!!!!!!!!!!!!!!!!!!");
  fs.appendFile(fileName,files,function(err){
  if(err){
  return;
  }
  });
  }else{//如果现有文件已经达到在新写入一个文件
  fileNums++;
  core_counters= 0;
  core_counters_all = 0;
  files = "";//清空缓存内容
  }
 
  }
  response.end();
  console.log("request   end..   ");
      }).listen(3000);
 
}

// 当主进程被终止时,关闭所有工作进程
process.on('SIGTERM', function () {
console.log('mainThread  sigterm!!');
for (var pid in workers) {
process.kill(pid);
}
process.exit(0);}
);

//**********************************************************************************

大家看看执行结果就知道了;


所以说不需要我们自己来考虑多进程的问题,就按照单进程来写代码就行,node cluster会自动进行负载均衡。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值