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

Кластерный режим PM2

PM2 — это диспетчер процессов для приложений Node.js, который позволяет пользователям легко управлять своими приложениями Node.js и поддерживать их бесперебойную работу. Благодаря кластерному режимуPM2 сетевые приложения Node.js можно масштабировать на все доступные ЦП без каких-либо изменений кода.

Например, если у вас есть сервер с 8 процессорами, вы можете запустить 8 экземпляров своего приложения и повысить производительность и надежность своего приложения.

Для запуска приложения в кластерном режиме вы можете легко создать файл конфигурации экосистемы и запустить свое приложение.

module.exports = {
    apps: [
        {
            name: 'app',
            script: 'build/app.js',
            instances: '8',
            autorestart: true,
            watch: false,
            max_memory_restart: '512M',
            vizion: false,
            exec_mode: 'cluster',
        },
    ],
};

Эта конфигурация позволяет вам запускать 8 воркеров на вашем сервере. И в большинстве случаев этого будет достаточно (особенно если у вас на сервере всего одно приложение).

Но представьте, что вы хотите добавить еще одно приложение на свой сервер. Конечно, вы хотите разделить ресурсы между вашими приложениями. Теперь вы меняете файл конфигурации для каждого приложения и устанавливаете 4 воркера для каждого приложения. Это будет работать до тех пор, пока какое-либо из ваших приложений не сможет справиться с возросшей нагрузкой трафика. Если одно из приложений использует 100% ЦП каждого воркера, вы должны добавить больше воркеров. В этом случае вы должны подключиться к своему серверу и использовать команду pm2 scale, чтобы масштабировать больше воркеров для загруженного приложения и уменьшить воркеры для другого приложения.

pm2 scale app +3 # Add 3 new additional instances for your app

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

Другой случай, например, у вас есть сервер с 48 процессорами, и вы хотите запускать на нем несколько приложений. Если вы запустите каждое приложение с instances=max, PM2 запустит 48 экземпляров и представьте, что каждый экземпляр использует примерно 100 МБ ОЗУ (~ 5 ГБ для всех экземпляров). Таким образом, если у вас есть 10 приложений, это означает, что вы будете использовать около 50 ГБ памяти сервера без какой-либо нагрузки на сервер. Вы неэффективно используете ресурсы своего сервера.

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

Модуль автомасштабирования PM2

Чтобы решить эту проблему, я написал плагин pm2-autoscale, который помогает оптимизировать производительность приложения, автоматически регулируя количество запущенных экземпляров в зависимости от загрузки процессора каждым приложением.

Для использования модуля pm2-autoscale его необходимо установить с помощью команды

pm2 install pm2-autoscale

Модуль поддерживает несколько вариантов конфигурации

  • scale_cpu_threshold Максимальное значение загрузки процессора одним из экземпляров приложения, при котором модуль попытается увеличить число экземпляров приложения. (по умолчанию 30)
  • release_cpu_threshold Среднее значение использования всех ЦП приложением, когда модуль будет уменьшать количество экземпляров приложения (по умолчанию 5)
  • debug Включить режим отладки для отображения журналов из модуля (по умолчанию false)

Чтобы изменить значения конфигурации модуля, вы можете использовать следующие команды:

pm2 set pm2-autoscale:debug true
pm2 set pm2-autoscale:scale_cpu_threshold 50

Теперь вы можете изменить конфигурацию своей экосистемы, чтобы запускать любое приложение с минимальным количеством необходимых экземпляров. Например, если у вас 8 процессоров и 2 приложения, вы можете установить instances=2 для каждого приложения и сохранить доступные ресурсы вашего сервера. Когда модуль обнаружит, что загрузка ЦП выше scale_cpu_threshold, он начнет увеличивать количество экземпляров до максимального CPUs-1 только в том случае, если на сервере есть свободная память. Когда модуль обнаруживает, что загрузка ЦП снижается, он останавливает бесполезные экземпляры.

Посмотрите пример, как это работает. Я протестировал его с помощью Apache Benchmark.

0|pm2-autoscale | App "app" has 1 worker(s). CPU: 0.
0|pm2-autoscale | App "app" has 1 worker(s). CPU: 17.
0|pm2-autoscale | App "app" has 1 worker(s). CPU: 29.
0|pm2-autoscale | INFO: Increase workers
0|pm2-autoscale | App "app" scaled with +1 worker
0|pm2-autoscale | App "app" has 2 worker(s). CPU: 26,34.
0|pm2-autoscale | App "app" has 2 worker(s). CPU: 29,43.
0|pm2-autoscale | App "app" has 2 worker(s). CPU: 28,38.
0|pm2-autoscale | INFO: Increase workers
0|pm2-autoscale | INFO: App "app" is busy
0|pm2-autoscale | App "app" scaled with +1 worker
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 27,35,33.
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 25,31,22.
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 24,29,23.
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 23,25,20.
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 15,18,17.
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 11,13,13.
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 8,9,10.
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 6,7,7.
0|pm2-autoscale | App "app" has 3 worker(s). CPU: 5,5,5.
0|pm2-autoscale | INFO: Decrease workers
0|pm2-autoscale | INFO: App "app" is busy
0|pm2-autoscale | App "app" decresed one worker
0|pm2-autoscale | App "app" has 2 worker(s). CPU: 4,4.
0|pm2-autoscale | App "app" has 2 worker(s). CPU: 3,3.
0|pm2-autoscale | App "app" has 2 worker(s). CPU: 2,2.
0|pm2-autoscale | INFO: Decrease workers
0|pm2-autoscale | INFO: App "app" is busy
0|pm2-autoscale | App "app" decresed one worker

Таким образом, если загрузка ЦП приложения высока, модуль может увеличить количество запущенных экземпляров для обработки нагрузки. Точно так же, если загрузка ЦП низкая, модуль может уменьшить количество запущенных экземпляров для экономии ресурсов.

Исходный код модуля доступен на GitHub https://github.com/VeXell/pm2-autoscale и если вы хотите что-то добавить/изменить — просто создайте пулреквест.

Спасибо, что прочитали эту статью. Надеюсь, вы нашли это полезным.