nodejs是单线程,这意味着Node只能利用一个处理器来工作。但多数服务器都有多个核。好在nodejs提供了cluster模块,可以把任务分配给子进程。每个子进程有些特殊能力,比如能与其他子进程共享socket连接。当用cluster时,主进程不会参与每个具体的事务中,主进程管理所有的子进程,但当子进程与I/O操作交互时,它们是直接进程操作的,不需要通过主进程。

一个简单的例子:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length; if(cluster.isMaster)
{
//创建工作进程
for(var i=0; i<numCPUs; i++)
{
cluster.fork();
} cluster.on('death', function(worker)
{
console.log('worker' + worker.pid + 'died');
});
}
else
{
//工作进程创建http服务
http.Server(function(req, res)
{
res.writeHead(200);
res.end("Hello world\n");
}).listen(8000);
}

  cluster工作的原理是每一个Node进程要么是主进程,要么成为工作进程。当一个主进程调用cluster.fork()方法时,它会创建于主进程一模一样的子进程,除了两个让每个进程可以检查自己是父/子进程的属性以外。在主进程cluster.isMaster会返回true,而cluster.isWorker()会返回false,在主进程中则相反。

  除了共享socket外,还能利用cluster做更多事情,因为它是基于child_process模块的,这个模块会提供一系列属性,其中最有用一些可以检查子进程健康状态,在上面例子中,当子进程死亡时,主进程会用console.log()输出死亡进程,既然监测到了死亡进程,那么我们可以在这个子进程死亡时,再重新创建一个新的子进程。

cluster.on('death', function(worker)
{
console.log('worker' + worker.pid + 'died');
cluster.fork();
});

  这个简单的改进让主进程不停地把死掉的进程重启,从而保证所有的CPU都有我们的服务器在运行。其实还可以做更多的事情,因为工作进程可以传消息给主进程,所以可以让每个工作进程报告自己的状态,如内存使用量。这让主进程可以察觉哪些工作进程变得不稳定,确认哪些工作进程没有冻结,或者被堵塞。

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length; var rssWarn = (12*1024*1024),
heapWarn = (12*1024*1024); if(cluster.isMaster)
{
//创建工作进程
for(var i=0; i<numCPUs; i++)
{
var worker = cluster.fork();
worker.on('message', function(m)
{
if(m.memory)
{
if(m.memory.rss > rssWarn)
{
console.log('Worker' + m.process + 'using too much momory.');
}
}
})
} cluster.on('death', function(worker)
{
console.log('worker' + worker.pid + 'died');
cluster.fork();
});
}
else
{
//工作进程创建http服务
http.Server(function(req, res)
{
res.writeHead(200);
res.end("Hello world\n");
}).listen(8000); //每秒报告一次状态
setInterval(function report()
{
process.send({memory: process.memoryUsage(), process: process.pid});
})
}

  这个例子中,工作进程报告自己的内存使用量,当子进程使用了过多内存时,主进程会发送一条警告到日志中去。这让node主进程有控制的能力,也带来了好处。这个消息传递接口也允许主进程把消息发回给工作进程。当然,我们还能用消息传递做更多的事情。

最新文章

  1. C语言 右左法则
  2. 谈一谈php://filter的妙用
  3. 让wego微购购物分享系统采集拍拍数据功能之腾讯paipai功能采集插件
  4. C# 从数据库中删除,插入,修改 索引选中条目
  5. 2016-1-3点菜系统demo的实现,pickerView的学习
  6. Unity C# 游戏间物体间的访问
  7. 柯南君:看大数据时代下的IT架构(5)消息队列之RabbitMQ--案例(Work Queues起航)
  8. c++爱问的面试问题
  9. python之字典常用语法
  10. Spark操作HBase问题:java.io.IOException: Non-increasing Bloom keys
  11. Akka(6): become/unbecome:运算行为切换
  12. Qwt安装(转)
  13. JavaScript Date 时间对象方法
  14. 给Ubuntu系统清理垃圾
  15. fiddler学习总结--利用fiddler快速模拟mock
  16. debian8.4 系统莫名没有声音
  17. LED音乐频谱之输入数据处理
  18. Hibernate5笔记7--Hibernate缓存机制
  19. Html5 Canvas 实现图片合成
  20. spring复杂数据类型传递

热门文章

  1. linux 源码安装
  2. PHP基础课程学习总结
  3. jquery 点击事件
  4. mongodb查询返回内嵌符合条件的文档
  5. 如何将arcgis的mxd文档存储为相对路径
  6. json和字符串转换
  7. LESS 学习记录(简单入门)
  8. JavaScript 常用算法
  9. 在django中使用自定义标签实现分页功能
  10. JavaScript(复习总结)