Если вы когда-то использовали Node.js, вы должны знать, что он однопоточный. Вот почему вы не сможете в полной мере использовать преимущества многоядерных машин, если не используете модуль кластер или диспетчер процессов, такой как PM2.
Я работаю над приложением, которое использует модуль кластера для управления процессами. Хотя в этом были некоторые преимущества, я решил перейти от кластерного модуля к PM2 и RabbitMQ. В этом блоге будут рассмотрены причины, по которым я сделал это изменение, и предоставлена информация о том, как и почему я перешел на PM2 и RabbitMQ.

Модуль кластера:
Модуль кластера в Node.js позволяет легко создавать дочерние процессы, которые все используют порты сервера. Я использовал кластерный модуль, чтобы
- Запустите несколько процессов самого приложения.
- Управляйте несколькими
child_processesдля разных задач, таких как отправка SMS, электронных писем, уведомлений.
В приведенном выше коде в кластере только один мастер, я получаю по одному дочернему процессу для каждого рабочего:
1 smsWorker + 1 emailWorker + 1 notifWorker + numCPUs app processes.С этой реализацией мне также пришлось управлять состоянием рабочего процесса. Если он выйдет из строя (по нескольким причинам), мне пришлось его перезапустить. После добавления этой функциональности код выглядит так:
Событие “disconnect” запускается всякий раз, когда рабочий погибает. Итак, я просто начинаю новый процесс cluster.fork().process;.
Единственное, что осталось в этой реализации, - это взаимодействие процессов между работниками приложений и работниками приложений с выделенной задачей (SMS / электронная почта / уведомление ) рабочие.
Связь процесса:
Модуль кластера предоставляет метод process.message для отправки сообщения мастеру. Благодаря этому я мог прослушивать различные сообщения из приложения и отправлять их соответствующему работнику. После добавления взаимодействия с процессом окончательный код выглядит так:
Я определил глобальные методы, чтобы отправлять сообщения работнику из любого места приложения. Когда я вызываю метод global.emailWorker.send(“Email to send”); из приложения, он отправляет сообщение главному процессу, а затем главный процесс пересылает его соответствующему child_process.
Вы заметите, как запускается global.smsWorker. global.smsWorker = require(‘child_process’).fork(‘./smsWorker’);
smsWorker.js, emailWorker.js & notifWorker.js файлы - это функция, которая прослушивает сообщения процесса для выполнения соответствующей задачи.
Чтобы получить более четкое представление о потоке взаимодействия между процессами, взгляните на это:

Эта реализация работает хорошо, но всегда есть свои плюсы и минусы.
Плюсы:
- Масштабируется в соответствии с количеством ядер ЦП, доступных на вашем компьютере.
- Легко управлять, так как нет зависимости от каких-либо других модулей / услуг.
- Легко реализовать процессную коммуникацию.
Минусы:
- Производительность приложения снижается, если сообщений слишком много.
- Эта реализация не кажется лучшей для управления коммуникацией преданных делу сотрудников.
- Вам нужно самостоятельно управлять состоянием процесса (без автоматизации).
- Невозможно запускать / останавливать / перезапускать (sms / email / notif) рабочих, не затрагивая приложение, потому что они связаны.
Мне пришлось переключиться на PM2 и RabbitMQ из-за проблем с производительностью. Поскольку выделенные воркеры связаны с основным приложением, я не мог запускать / останавливать отдельных воркеров, и стало трудно поддерживать их отдельно в этой реализации.
PM2, менеджер процессов для Node.js:
PM2 - это менеджер процессов для приложений Node.js. Это позволяет вам эффективно управлять несколькими процессами. Он имеет множество функций, в том числе:
- Автоматический перезапуск приложения при изменении кода с помощью Watch & Reload.
- Легкое управление процессами.
- Мониторинг возможностей процесса.
- Автоматический перезапуск, если система достигает предела max memory или происходит сбой.
- Мониторинг ключевых показателей в сети.
Чтобы настроить PM2, я просто добавил файл конфигурации в корень каталога приложения.
PM2 также может использовать кластерный модуль и управлять им самостоятельно. Я настроил app процесс для запуска cluster_mode с max возможными процессами, доступными на машине. Все зависит от количества ядер.
Поскольку процессы разделены, теперь я могу запускать / останавливать / перезапускать их с помощью pm2.config.js, т.е.
pm2 start pm2.config.js // start all processespm2 stop app // stop app processespm2 restart smsWorker // restart smsWorker
Это решает проблему управления всеми рабочими. Для управления взаимодействием процессов, поскольку все приложения работают как отдельный процесс, вы больше не можете использовать process.send(message); функцию. Вот почему я решил использовать RabbitMQ в качестве брокера сообщений.
RabbitMQ, брокер сообщений:
RabbitMQ - один из наиболее широко используемых брокеров сообщений с открытым исходным кодом. Для обмена сообщениями используется протокол amqp. RabbitMQ имеет множество функций, в том числе:
- Постоянные очереди сообщений
- Множественные типы обмена
- Легкий мониторинг и управление для любой среды
Я использую модуль amqplib для Node.js с типом обмен темами. Я не буду здесь вдаваться в подробности реализации RabbitMQ, потому что для этого нужна целая статья. Может в следующий раз.
Я полностью удалил файл cluster-module.js (показанный выше) из приложения и создал worker-mq.js:
Здесь вместо отправки сообщения в обработку вы можете опубликовать его на бирже RabbitMQ. Рабочие, подписанные на process.on(‘message’), теперь слушают обмен RabbitMQ. Приведенный выше smsWorker.js теперь выглядит так:
В текущей реализации все рабочие остаются независимыми друг от друга, и RabbitMQ берет на себя ответственность за обмен данными.

Плюсы:
- PM2 управляет всеми процессами.
- Запустить / остановить / перезапустить любого воркера легко.
- Рабочие остаются независимыми друг от друга.
- В процессе Node.js коммуникационные сообщения отсутствуют.
Минусы:
- RabbitMQ не так-то просто внедрить в производство.
- Добавляет зависимость модулей PM2 и RabbitMQ.
- Необходимо управлять / контролировать сервер RabbitMQ вместе с PM2.
В настоящее время в моих настройках работники sms / email / notif полностью разделены. Надеюсь, в следующем посте я напишу о переносе их на Serverless (AWS Lambda), что является для них лучшим местом.
Если вы разрабатываете на Node.js, ознакомьтесь с другими статьями по:
- Как имитировать экспресс-сессию.
- Создайте свое первое бессерверное приложение на Node.js с помощью AWS Lambda, S3 и API Gateway.
Если вам понравился этот пост, не забудьте поделиться и подписаться.
@ waleedashraf01
github.com/waleedashraf