Я построил встроенную кластерную архитектуру Node.js с конфигурацией мастер / рабочий.Приложение использует express
для обслуживания API и статических файлов, и оно развернуто с помощью Docker:
[D O C K E R: 8080] --- N ---> [W O R K E R: 3001 ] --- 1 ---> [M A S T E R: 3000]
У меня N работника в Worker.js
и 1 мастер в master.js
.Мастер и работник совместно используют общие модули, в то время как мастер имеет основной модуль, который загружает основные сервисы и предоставляет API на PORT=3001
, а работник загружает другие API на PORT=3000
, где контейнер Docker был привязан.В то время как прокси-сервер маршрутизации на Worker будет пересылать запросы ведущему устройству для обслуживания запросов к основным модулям, другие запросы напрямую обрабатываются сервером на 3000.
Стартовый скрипт выглядит как
'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);
У меня следующий вопрос.
1) По умолчанию модуль cluster
совместно использует подчеркивающее HTTP-соединение, используя round-robin подход для обслуживания запросов - см. здесь , где рабочие процессы создаются с помощью child_process.fork () .Я не знаю, смогу ли я настроить этот метод для распределения входящих соединений.
2) До сих пор я работаю со статическими файлами, шаблонами (такими как pig / swig) в экспресс-веб-приложении накаждый рабочий в PORT=3000
, что означает, что я запускаю статические маршруты для веб-приложения на каждом рабочем экземпляре.Я не уверен, что это с точки зрения использования памяти - лучший подход.
3) Другой подход кластеризации.Я спрашивал о переносе этой архитектуры на PM2, несмотря на то, что она кажется многообещающей, я не уверен, что это лучший вариант - подробнее см. здесь .