脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-[Node.js] Cluster,把多核用起来,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。 引子
众所周知,虽然Node的底层有一个IO线程池,但其应用层默认是单线程运行的,对于多核CPU环境来说,是一种资源的浪费。
所幸Node提供了child_PRocess 模块,让开发者得以开多个进程,实现每个进程各自利用一个CPU,以实现多核的利用。
child_process 模块给予Node 可以随意创建子进程的能力。因为 child_process 类本身是一个 EventEmITter,所以进程间通信很容易;且父子进程间通信并不通过网络层,而是在内核中完成,高效。
但 child_process 对于开发者来说,编程模型还是过于复杂,需要操心的细节过多,比如:父进程崩溃了,子进程回收是需要开发者提供代码来处理的——如果开发者只是想单纯利用多核模型,对具体工作进程的控制粒度并没有太多设想,那这种开发模型无疑是令人头疼的。
针对这个问题,Node 提供了 Cluster 模块。Cluster 简化了父子模型编程模型,只区分:当前进程是不是 Master,是 Master 就可以fork子进程,不是那就请行使Worker 职责。至于什么资源的回收,负载的调配,uncaughtException的处理,它自有安排。
本质上, Cluster 是 child_process 和 net 模块的组合应用。它不仅简化了编程模型,还使得共享监听同一端口成为可能。
更多关于Cluster的原理这里不表,感兴趣可以移步 → 解读Nodejs多核处理模块cluster
场景
用Node快速搭站呢,当然就用 exPress 咯 :) 所以,需求就是用 Cluster 做个单机集群,多进程跑 express,提升站点的吞吐量。
实验
先用 express-generator 搭个框子,模板引擎还是使 ejs 吧:
express -e myapp2
express-generator 默认会把 app.js 生成好,一行代码不写,一个完备的 http server 是已经实现的了。So,我们可以实现一个 Cluster 单机集群,clusterMaster.js:
复制代码
//CPU几核?
VAR cpus = require('os').cpus().length;
//子进程监听消息处理函数
var workerListener = function (msg) {
if (msg.access)
console.LOG('user access %s, worker [%d]',
msg.access, msg.workerid);
};
//fork新的子进程函数
var forkWorker = function(listener){
var worker = cluster.fork();
console.log('worker [%d] has been created',
worker.process.pid);
worker.on('message', listener);
return worker;
};
//Cluster处理
var cluster = require('cluster');
if (cluster.isMaster) {
for (var i = 0; i < cpus; i++) {
forkWorker(workerListener);
}
} else {
var app = require('./app');
return app.listen(3000);
}
//Cluster收到子进程退出消息
cluster.on('exit', function (worker, code, signal) {
console.log('worker [%d] died %s, fork a new one.',
worker.process.pid, code || signal);
forkWorker(workerListener);
});
//Cluster收到子进程运行消息
cluster.on('online', function(worker){
console.log('worker [%d] is running.', worker.process.pid);
});
复制代码
可以看到:
Cluster 是通过 isMaster 来区分父子进程的。父进程中处理创建逻辑:根据 CPU的核数,创建相应数量的子进程;子进程中运行具体的 Server 创建代码。够简单的模型~
在 Cluster 父进程端,是始终能获知 当前worker 的。而当前 worker 的 pid 呢,在有worker 句柄情况下,对应的是 woker.process.pid;在子进程运行的上下文中,就是 process.pid。这不难理解~
我们为新fork出来的子进程添加了消息处理函数,使得任何子进程运行代码,都可以随时利用消息触发它:用途挺广泛的,稍后会演示一个例子
在子进程退出时,Cluster 父进程会收到 exit 消息,这时会重fork一个新子进程来补缺
假设用户访问这个站点: localhost:3000/,我希望告诉他,是哪个子进程在为他渲染页面。那么,在 /routes/ 添加一个express 路由 index.js:
复制代码
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res) {
res.render('index', { title: 'Express',
workerid: process.pid });
process.send({access: '/', workerid: process.pid});
});
module.exports = router;
复制代码
可以看到,除了路由,还使用 process.send 发送了消息,它实际上会触发之前代码中子进程注册的 workerListener,向它汇报路径和进程号;由于使用了 render,那自然是少不了 ejs 模板, /views/index.js:
复制代码
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
<p>[<%= workerid %>] worker is serving for you.</p>
</body>
</html>
复制代码
模板会将 render 携带的子进程 pid 渲染到页面上; 当然少不了在 app.js 中添加路由映射:
var routes = require('./routes/index');
app.use('/', routes);
觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! js脚本,巧夺天工,精雕玉琢。小宝典献丑了!
以上是脚本宝典为你收集整理的javascript代码实例教程-[Node.js] Cluster,把多核用起来全部内容,希望文章能够帮你解决javascript代码实例教程-[Node.js] Cluster,把多核用起来所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。