nodejs:使用多处理器
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主进程有控制的能力,也带来了好处。这个消息传递接口也允许主进程把消息发回给工作进程。当然,我们还能用消息传递做更多的事情。
最新文章
- C语言 右左法则
- 谈一谈php://filter的妙用
- 让wego微购购物分享系统采集拍拍数据功能之腾讯paipai功能采集插件
- C# 从数据库中删除,插入,修改 索引选中条目
- 2016-1-3点菜系统demo的实现,pickerView的学习
- Unity C# 游戏间物体间的访问
- 柯南君:看大数据时代下的IT架构(5)消息队列之RabbitMQ--案例(Work Queues起航)
- c++爱问的面试问题
- python之字典常用语法
- Spark操作HBase问题:java.io.IOException: Non-increasing Bloom keys
- Akka(6): become/unbecome:运算行为切换
- Qwt安装(转)
- JavaScript Date 时间对象方法
- 给Ubuntu系统清理垃圾
- fiddler学习总结--利用fiddler快速模拟mock
- debian8.4 系统莫名没有声音
- LED音乐频谱之输入数据处理
- Hibernate5笔记7--Hibernate缓存机制
- Html5 Canvas 实现图片合成
- spring复杂数据类型传递