Задать вопрос

Почему nodejs в кластерном режиме показывает результат производительности хуже чем в одном инстансе?

Итак, обо всем подробнее.
Все начинается с NGINX, он направляет запросы на backend (express.js), в одном случае на один порт в другом на кластер (несколько портов, но все на той же физической машине).
Если express запущен в стандартном режиме (кастомный конфиг), то все происходит как обычно, сервер стартует на одном порте. Если запускаем в кластерном, то создаем мастер-процесс (cluster.isMaster) и создаем дочерние стартуя сервер в нескольких инстансах (равное кол-ву ядер цп) - все это тоже стандартный подход.
Но, когда тестили все это с помощью jmeter (100 одновременных запросов), обнаружили что в кластерном режиме производительность в два-три раза хуже чем в обычном. Хотя, очевидно же что в кластерном производительность должна быть выше, т.к. в стандартном режиме используется один процесс и одно ядро, а в кластерном - 8.

Есть у меня еще вариант попробовать PM2, там как я понял запуск сервера происходит иначе, но интересно все же понять почему в моей ситуации происходит так?
  • Вопрос задан
  • 665 просмотров
Подписаться 7 Средний 3 комментария
Решения вопроса 1
bingo347
@bingo347 Куратор тега Node.js
Crazy on performance...
https://nodejs.org/dist/latest-v10.x/docs/api/clus...

Сам по себе кластер, на всех ОС кроме винды, делает accept соединений в мастер процессе и передает воркерам уже установленное tcp соединение с клиентом, это позволяет балансировать нагрузку алгоритмом round-robin (каждому воркеру дается примерно равное количество соединений, так как они раздаются строго по очереди), но это же накладывает издержки на передачу файлового дескриптора соединения между мастер и воркер процессами при каждом соединении.

Вариантов оптимизации тут 2:
1. Nginx должен открывать соединения с бэкендом в режиме keep-alive. Так минимизируются издержки не только на передачу соединения воркеру, но и вообще на его открытие, что даст ощутимый прирост производительности под нагрузкой.
2. Вместо модуля cluster использовать обычный child_process и управлять передачей соединений вручную, а точнее передавать не уже открытые соединения, а слушающий сокет. В этом случае балансировка будет происходить на уровне ОС. Как пишут в документации к cluster, это может привести к неравномерной загрузке воркеров, так как соединение будет доставаться тому воркеру, который первым успеет сделать accept. Зато уберет издержки на передачу каждого соединения между процессами. Но даже при этом варианте, keep-alive крайне желателен.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы