Кластер NodeJS, действительно ли он нужен?

Я решил, что хочу исследовать, как лучше всего обрабатывать большой объем трафика с помощью сервера NodeJS, я провел небольшой тест на 2 серверах Digital Ocean, которые имеют 1 ГБ ОЗУ / 2 процессора Код сервера No-Cluster:

// Include Express
var express = require('express');

// Create a new Express application
var app = express();

// Add a basic route – index page
app.get('/', function (req, res) {
    res.redirect('http://www.google.co.il');
});

// Bind to a port
app.listen(3000);
console.log('Application running');

Код сервера кластера:

    // Include the cluster module
var cluster = require('cluster');
// Code to run if we're in the master process
if (cluster.isMaster) {
    // Count the machine's CPUs
    var cpuCount = require('os').cpus().length;

    // Create a worker for each CPU
    for (var i = 0; i < cpuCount; i += 1) {
        cluster.fork();
    }
// Code to run if we're in a worker process
} else {
    // Include Express
    var express = require('express');

    // Create a new Express application
    var app = express();

    // Add a basic route – index page
    app.get('/', function (req, res) {
        res.redirect('http://www.walla.co.il');
    });

    // Bind to a port
    app.listen(3001);
    console.log('Application running #' + cluster.worker.id);
}

И я отправил запросы стресс-теста на эти серверы, я исключил, что сервер кластера будет обрабатывать больше запросов, но этого не произошло, оба сервера упали при одинаковой нагрузке, хотя на кластере работали 2 службы узла и 1 служба на другом. -кластер.

Теперь мне интересно, почему? Я сделал что-то не так?

Может быть, что-то еще заставляет серверы достигать точки останова? оба сервера падали при ~800 rps


person Roy Hershko    schedule 01.01.2018    source источник
comment
Было ли всего 2 процесса узла или всего 3 процесса узла?, потому что, включая мастер, вам потребуется 3 процесса узла в кластере   -  person Malice    schedule 01.01.2018
comment
да это было 3 процесса :) я ленив в фактах   -  person Roy Hershko    schedule 01.01.2018


Ответы (2)


Теперь мне интересно, почему? я сделал что-то не так?

Ваш тестовый сервер не делает ничего, кроме res.redirect(). Если ваши обработчики запросов практически не используют ЦП, то вы вообще не будете привязаны к ЦП, и вы не выиграете от привлечения большего количества ЦП. Ваш кластер будет узким местом при обработке входящих подключений, которая будет примерно одинаковой с кластеризацией или без нее.

Теперь добавьте в обработчик запросов значительную загрузку ЦП, и вы должны получить другой результат.

Например, изменить на это:

// Add a basic route – index page
app.get('/', function (req, res) {

    // spin CPU for 200ms to simulate using some CPU in the request handler
    let start = Date.now();
    while (Date.now() - start < 200) {}

    res.redirect('http://www.walla.co.il');
});

Запуск тестов — это здорово, но вы должны быть осторожны, что именно вы тестируете.

person jfriend00    schedule 01.01.2018

То, что говорит @jfriend00, верно; на самом деле вы не поднимаете достаточно тяжестей, чтобы оправдать это, однако на самом деле вы не делите нагрузку. Глянь сюда:

app.listen(3001);

Вы не можете привязать две службы к одному и тому же порту, чтобы ОС волшебным образом балансировала их нагрузку[1]; попробуйте добавить обработчик ошибок на app.listen() и посмотрите, получите ли вы ошибку, например.

app.listen(3001, (err) => err ? console.error(err));

Если вы хотите сделать это, вам придется принять все в своем мастере, затем поручить рабочим выполнить задачу, а затем снова передать результаты обратно мастеру.

Однако обычно проще не сделать это в программе Node; ваш интерфейс по-прежнему будет ограничивающим фактором. Более простым (и быстрым) способом может быть размещение специального балансировщика нагрузки перед несколькими запущенными экземплярами вашего приложения (например, HAProxy или Nginx).


[1]: На самом деле это ложь; Извините. Вы можете сделать это, указав SO_REUSEPORT при первоначальном вызове bind, но вы не можете явно указать это в Node, и Node не указывает это за вас... поэтому вы не можете в Узел.

person slugonamission    schedule 01.01.2018