Node.js Кластерная архитектура: как масштабировать мастер работника - PullRequest
0 голосов
/ 19 октября 2018

Я построил встроенную кластерную архитектуру 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, несмотря на то, что она кажется многообещающей, я не уверен, что это лучший вариант - подробнее см. здесь .

1 Ответ

0 голосов
/ 19 октября 2018

Мастер должен заботиться только о том, чтобы запускать рабочих и правильно их выключать / следить за сигналами от хоста и реагировать соответствующим образом.По моему опыту, у меня были хитрые ошибки, потому что я показал API на мастере, который должен был быть на рабочем.

Если вы планируете переключиться на PM2, PM2 будет обрабатывать вашего мастера, и вам понадобитсяв любом случае переместить этот код работнику (или, по крайней мере, так было раньше)

Относительно ваших вопросов;

  1. Если у вас есть необходимость переопределить циклический перебор илинастройте его, я думаю, у вас есть цель направить один и тот же клиентский трафик одному и тому же работнику, то есть Sticky Sessions. Есть способы сделать это , но есть ограничения;если вы используете обратный прокси-сервер, такой как nginx или haproxy, перед узлом (что вам следует), а также хотите, чтобы сокеты работали должным образом (и в игре был Docker), вы не можете по-настоящему разветвляться на рабочих, потому что IP, который вы видите(на котором вы будете вычислять липкий идентификатор сеанса) всегда будет принадлежать вашему прокси или хосту докера (даже с заголовком x-forwarded-for), что в первую очередь побеждает цель кластеризации.-> Мое решение состояло в том, чтобы запустить каждого работника на новом порту (например, 3001, 3002 ... 300N) и позволить nginx обрабатывать липкие сессии
  2. Это не проблема, но не идеально - и да, память немного увеличится, потому что каждый работник загружает маршруты и модули.Но nginx намного быстрее обрабатывает статические файлы (и обрабатывает кеш для него со многими http-заголовками), чем узел.Поэтому вы должны полагаться на статистику обслуживания nginx и сохранять узел для динамических запросов (например, / api / login и т. Д.)
  3. PM2 - это хорошее решение, которое имеет много расширенных функций, таких как статистика отчетов и обрабатывает развертывания без простоев, нотакже стоит денег в зависимости от того, какие функции вы хотите использовать
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...