Если вы когда-то использовали 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. Это позволяет вам эффективно управлять несколькими процессами. Он имеет множество функций, в том числе:

Чтобы настроить PM2, я просто добавил файл конфигурации в корень каталога приложения.

PM2 также может использовать кластерный модуль и управлять им самостоятельно. Я настроил app процесс для запуска cluster_mode с max возможными процессами, доступными на машине. Все зависит от количества ядер.

Поскольку процессы разделены, теперь я могу запускать / останавливать / перезапускать их с помощью pm2.config.js, т.е.

  • pm2 start pm2.config.js // start all processes
  • pm2 stop app // stop app processes
  • pm2 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, ознакомьтесь с другими статьями по:

Если вам понравился этот пост, не забудьте поделиться и подписаться.
@ waleedashraf01
github.com/waleedashraf