Как увеличить пропускную способность на сервере NodeJS с помощью кластера?

у меня есть сервер NodeJS (Express), и я распространяю запросы на несколько процессоров, используя пример кластерного модуля на сайте nodeJs.

if (cluster.isMaster) {
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  };
  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
    cluster.fork();
  });
} else {  
  server.listen(app.get('port'), function(){
    console.log('HTTP server on port ' + app.get('port') + ' - running as ' + app.settings.env);
  });

  // setup socket.io communication
  io.sockets.on('connection', require('./app/sockets'));
  io.sockets.on('connection', require('./app/downloadSockets'));
}

проблема в том, что бенчмарк из siege показывает мне, что нет увеличения количества попаданий. Это выход осады:

$ siege -c100 192.168.111.1:42424  -t10S
** SIEGE 3.0.5
** Preparing 100 concurrent users for battle.
The server is now under siege...
Lifting the server siege...      done.

Transactions:               1892 hits
Availability:             100.00 %
Elapsed time:              10.01 secs
Data transferred:           9.36 MB
Response time:              0.01 secs
Transaction rate:         189.01 trans/sec
Throughput:             0.93 MB/sec
Concurrency:                1.58
Successful transactions:        1892
Failed transactions:               0
Longest transaction:            0.05
Shortest transaction:           0.00

После Кластеризации :

$ siege -c100 192.168.111.1:42424  -t10S
** SIEGE 3.0.5
** Preparing 100 concurrent users for battle.
The server is now under siege...
Lifting the server siege...      done.

Transactions:               1884 hits
Availability:             100.00 %
Elapsed time:               9.52 secs
Data transferred:           9.32 MB
Response time:              0.01 secs
Transaction rate:         197.90 trans/sec
Throughput:             0.98 MB/sec
Concurrency:                1.72
Successful transactions:        1884
Failed transactions:               0
Longest transaction:            0.07
Shortest transaction:           0.00

означает ли это, что мой сервер уже получает максимальную пропускную способность с одним сервером, вероятно, потому, что его локальная машина или возможно, он не может получить 4 процессора, так как слишком много процессов работает, я не уверен.

как использовать кластерный модуль для увеличения throghput и почему мой текущий код не пройти ? Также я проверил, что он действительно создает 4 экземпляра сервера i.e кластер.вилка работает. Любые советы были бы очень полезны.

2 ответов


эффект достигается за счет кластеризации или роста параллельных запросов (попробуйте увеличить число одновременных пользователей до 300-400). Или задачи, которые дают серьезную нагрузку. Проведем более интересный тест: загрузим файл размером около 1 МБ, плюс сделаем задержку 5 мсек и 50 мсек для эмуляции сложных операций. Для четырехъядерного процессора при локальном тестировании будет следующим (соответственно для обычного и кластерного):

$ siege -c100 http://localhost/images/image.jpg  -t10S

нормальный режим (5 мсек задержка):

Lifting the server siege...      done.
Transactions:                    1170 hits
Availability:                 100.00 %
Elapsed time:                   9.10 secs
Data transferred:             800.79 MB
Response time:                  0.27 secs
Transaction rate:             128.57 trans/sec
Throughput:                    88.00 MB/sec
Concurrency:                   34.84
Successful transactions:        1170
Failed transactions:               0
Longest transaction:            0.95
Shortest transaction:           0.01

режим кластера (задержка 5 мс):

Lifting the server siege...      done.
Transactions:                    1596 hits
Availability:                 100.00 %
Elapsed time:                   9.04 secs
Data transferred:            1092.36 MB
Response time:                  0.06 secs
Transaction rate:             176.55 trans/sec
Throughput:                   120.84 MB/sec
Concurrency:                    9.81
Successful transactions:        1596
Failed transactions:               0
Longest transaction:            0.33
Shortest transaction:           0.00

нормальный режим (задержка 50 мс):

Lifting the server siege...      done.
Transactions:                     100 hits
Availability:                 100.00 %
Elapsed time:                   9.63 secs
Data transferred:              68.44 MB
Response time:                  5.51 secs
Transaction rate:              10.38 trans/sec
Throughput:                     7.11 MB/sec
Concurrency:                   57.18
Successful transactions:         100
Failed transactions:               0
Longest transaction:            7.77
Shortest transaction:           5.14

режим кластера (задержка 50 мсек):

Lifting the server siege...      done.
Transactions:                     614 hits
Availability:                 100.00 %
Elapsed time:                   9.24 secs
Data transferred:             420.25 MB
Response time:                  0.90 secs
Transaction rate:              66.45 trans/sec
Throughput:                    45.48 MB/sec
Concurrency:                   59.59
Successful transactions:         614
Failed transactions:               0
Longest transaction:            1.50
Shortest transaction:           0.50

вы на самом деле ничего не делаете в своем примере. Подключитесь к mysql и запустите тяжелый запрос или сделайте http-запрос, который занимает несколько секунд. Вы замечаете, что в конечном итоге вы будете кодировать что-то (или использовать стороннюю библиотеку), которая заблокирует цикл событий. Это когда кластеризация будет важна, так как вы по существу будете иметь цикл событий для каждого процессора. Если один запрос медленный, и цикл событий должен ждать его, он не остановит новые запросы, которые поражают ваш API / application.

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