1. cluster 介绍
大家都知道 nodejs 是一个单进程单线程的服务器引擎, 不管有多么的强大硬件, 只能利用到单个 CPU 进行计算. 所以, 有人开发了第三方的 cluster, 让 node 可以利用多核 CPU 实现并行. 随着 nodejs 的发展, 让 nodejs 上生产环境, 就必须是支持多进程多核处理! 在 V0.6.0 版本, Nodejs 内置了 cluster 的特性. 自此, Nodejs 终于可以作为一个独立的应用开发解决方案, 映入大家眼帘了.
cluster 是一个 nodejs 内置的模块, 用于 nodejs 多核处理. cluster 模块, 可以帮助我们简化多进程并行化程序的开发难度, 轻松构建一个用于负载均衡的集群.
2. cluster 的工作原理
每个 worker 进程通过使用 child_process.fork() 函数, 基于 IPC(Inter-Process Communication, 进程间通信), 实现与 master 进程间通信.
当 worker 使用 server.listen(...) 函数时 , 将参数序列传递给 master 进程. 如果 master 进程已经匹配 workers, 会将传递句柄给工人. 如果 master 没有匹配好 worker, 那么会创建一个 worker, 再传递并句柄传递给 worker.
在边界条件, 有 3 个有趣的行为:
注: 下面 server.listen(), 是对底层 "http.Server-->net.Server" 类的调用.
1. server.listen({fd: 7}): 在 master 和 worker 通信过程, 通过传递文件, master 会监听 "文件描述为 7", 而不是传递 "文件描述为 7" 的引用.
2. server.listen(handle):master 和 worker 通信过程, 通过 handle 函数进行通信, 而不用进程联系
3. server.listen(0): 在 master 和 worker 通信过程, 集群中的 worker 会打开一个随机端口共用, 通过 socket 通信, 像上例中的 57132
当多个进程都在 accept() 同样的资源的时候, 操作系统的负载均衡非常高效. Node.js 没有路由逻辑, worker 之间没有共享状态. 所以, 程序要设计得简单一些, 比如基于内存的 session.
因为 workers 都是独力运行的, 根据程序的需要, 它们可以被独立删除或者重启, worker 并不相互影响. 只要还有 workers 存活, 则 master 将继续接收连接. Node 不会自动维护 workers 的数目. 我们可以建立自己的连接池.
3. cluster 的 API
官网地址: http://nodejs.org/api/cluster.html#cluster_cluster
cluster 对象
cluster 的各种属性和函数
cluster.setttings: 配置集群参数对象
cluster.isMaster: 判断是不是 master 节点
cluster.isWorker: 判断是不是 worker 节点
Event: 'fork': 监听创建 worker 进程事件
Event: 'online': 监听 worker 创建成功事件
Event: 'listening': 监听 worker 向 master 状态事件
Event: 'disconnect': 监听 worker 断线事件
Event: 'exit': 监听 worker 退出事件
Event: 'setup': 监听 setupMaster 事件
cluster.setupMaster([settings]): 设置集群参数
cluster.fork([env]): 创建 worker 进程
cluster.disconnect([callback]): 关闭 worket 进程
cluster.worker: 获得当前的 worker 对象
cluster.workers: 获得集群中所有存活的 worker 对象
worker 对象
worker 的各种属性和函数: 可以通过 cluster.workers, cluster.worket 获得.
worker.id: 进程 ID 号
worker.process: ChildProcess 对象
worker.suicide: 在 disconnect() 后, 判断 worker 是否自杀
worker.send(message, [sendHandle]): master 给 worker 发送消息. 注: worker 给发 master 发送消息要用 process.send(message)
worker.kill([signal='SIGTERM']): 杀死指定的 worker, 别名 destory()
worker.disconnect(): 断开 worker 连接, 让 worker 自杀
Event: 'message': 监听 master 和 worker 的 message 事件
Event: 'online': 监听指定的 worker 创建成功事件
Event: 'listening': 监听 master 向 worker 状态事件
Event: 'disconnect': 监听 worker 断线事件
Event: 'exit': 监听 worker 退出事件
4. master 和 worker 的通信的例子
- var cluster = require('cluster');
- var http = require('http');
- var numCPUs = require('os').cpus().length;
- if (cluster.isMaster) {
- console.log('[master]' + "master started, pid:" + process.pid);
- cluster.on('fork', function (worker) {
- console.log('[master]' + 'fork: worker' + worker.id);
- });
- cluster.on('online', function (worker) {
- console.log('[master]' + 'online: worker' + worker.id);
- });
- cluster.on('listening', function (worker, address) {
- console.log('[master]' + 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', address:' + address.address + ":" + address.port);
- });
- cluster.on('disconnect', function (worker) {
- console.log('[master]' + 'disconnect: worker' + worker.id);
- });
- cluster.on('exit', function (worker, code, signal) {
- console.log('[master]' + 'exit worker' + worker.id + 'died, try to fork a new worker.');
- cluster.fork();
- });
- for (var i = 0; i < numCPUs; i++) {
- cluster.fork();
- }
- Object.keys(cluster.workers).forEach(function (id) {
- cluster.workers[id].on('message', function (msg) {
- console.log('[master]' + 'received msg:' + msg + 'from worker' + id);
- });
- });
- function eachWorker(callback) {
- for (var id in cluster.workers) {
- callback(cluster.workers[id]);
- }
- }
- var i = 0;
- setTimeout(function () {
- eachWorker(function (worker) {
- i++;
- worker.send('[master]' + 'send msg' + i + 'to worker' + worker.id);
- });
- }, 3000);
- } else if (cluster.isWorker) {
- console.log('[worker]' + "worker" + cluster.worker.id + "started, pid:" + process.pid);
- process.on('message', function (msg) {
- console.log('[worker] worker' + cluster.worker.id + 'received msg:' + msg);
- process.send('[worker] send msg' + cluster.worker.id + 'to master.');
- });
- http.createServer(function (req, res) {
- var response = 'worker received request, id:' + cluster.worker.id + ',pid:' + process.pid;
- console.log(response);
- res.writeHead(200, { "content-type": "text/html" });
- res.end(response);
- }).listen(5000);
- }
来源: https://www.cnblogs.com/netfocus/p/4087619.html