我的Node.js应用具有主/工作集群架构。
基本上我的运行脚本run.js
就像
'use strict';
(function() {
/// node clustering
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) { // master node
var masterConfig=require('./config/masterconfig.json');
// Fork workers.
var maxCPUs = process.env.WORKER_NUM || masterConfig.cluster.worker.num;
maxCPUs=(maxCPUs>numCPUs)?numCPUs:maxCPUs;
for (let i = 0; i < maxCPUs; i++) {
const worker=cluster.fork();
}
var MasterNode=require('./lib/master');
var master= new MasterNode(masterConfig);
master.start()
.then(done=> {
console.log(`Master ${process.pid} running on ${masterConfig.pubsub.node}`);
})
.catch(error=> { // cannot recover from master error
console.error(`Master ${process.pid} error`,error.stack);
process.exit(1);
});
}
else if (cluster.isWorker) { // worker node
var workerConfig=require('./config/workerconfig.json');
var WorkerNode=require('./lib/worker');
var worker= new WorkerNode(workerConfig);
worker.start()
.then(done=> {
console.log(`Worker ${process.pid} running on ${workerConfig.pubsub.node}`);
})
.catch(error=> { // worker error is recoverable
console.error(`Worker ${process.pid} error`,error.stack);
});
}
}).call(this);
我正在主节点和工作节点上都启动HTTP服务器。当工作人员正在侦听端口3000时,主服务器正在侦听端口3001,该端口将映射到Docker容器实例上的8080:
[D O C K E R: 8080] --- N ---> [W O R K E R: 3001 ] --- 1 ---> [M A S T E R: 3000]
因此,侦听PORT 3001上WORKER的调度程序API将在需要时将请求转发到MASTER上的端口3000(例如,仅对于在主实例上运行的服务)。 所有MASTER / WORKER节点共享相同的代码库,但是某些模块一次在MASTER上加载,而其他模块在所有WORKER模块上重复,因此我有类似的东西:
root/
|
lib/
package.json
--- master.js
--- worker.js
--- run.js
默认情况下,节点集群基于child_process_fork使用循环机制在工作进程之间分配请求:
The cluster module supports two methods of distributing incoming connections.
The first one (and the default one on all platforms except Windows), is the round-robin approach, where the master process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process.
有关更多详细信息,请参见here。 我想获得对该架构的更多控制权,例如拥有一种定义自定义排队机制而不是循环机制的方法,或者将我当前的设置迁移到诸如PM2之类的某些流程管理工具而无需更改整个应用程序。>