Restart strategies
When starting application with PM2, application are automatically restarted on auto exit, event loop empty (node.js) or when application crash.
But you can also configure extra restart strategies like:
- Restart app at a specified CRON time
- Restart app when files have changed
- Restart when app reach a memory threshold
- Delay a start and automatic restart
- Disable auto restart (app are always restarted with PM2) when crashing or exiting by default)
- Restart application automatically at a specific exponential increasing time
Restart at cron time
Via CLI:
$ pm2 start app.js --cron-restart="0 0 * * *"
# Or when restarting an app
$ pm2 restart app --cron-restart="0 0 * * *"
Via configuration file, use the cron_restart
attribute:
module.exports = {
apps : [{
name: 'Business News Watcher',
script: 'app.js',
instances: 1,
cron_restart: '0 0 * * *',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
}
To disable cron restart:
pm2 restart app --cron-restart 0
Restart on file change
PM2 can automatically restart your application when a file is modified in the current directory or its subdirectories:
Via CLI:
$ pm2 start app.js --watch
Note: If an application is started with the --watch
option, stopping the app will not prevent it to be restarted on file change.
To totally disable the watch feature, do: pm2 stop app --watch
or toggle the watch option on application restart via pm2 restart app --watch
.
Via configuration file, use the watch: true
attribute:
module.exports = {
script: "app.js",
watch: true
}
You can specify which folder to watch for change, ignore folder and watch files interval with these options:
module.exports = {
script: "app.js",
// Specify which folder to watch
watch: ["server", "client"],
// Specify delay between watch interval
watch_delay: 1000,
// Specify which folder to ignore
ignore_watch : ["node_modules", "client/img"],
}
Memory based restart strategy
PM2 allows to reload (auto fallback to restart if not in cluster) an application based on a memory limit/ Please note that the PM2 internal worker (which checks memory), starts every 30 seconds, so you may have to wait a bit before your process gets restarted automatically after reaching the memory threshold.
CLI:
$ pm2 start api.js --max-memory-restart 300M
Via configuration file, use the max_memory_restart
attribute:
module.exports = {
script: 'api.js',
max_memory_restart: '300M'
}
Note: Units can be K(ilobyte) (e.g. 512K
), M(egabyte) (e.g. 128M
), G(igabyte) (e.g. 1G
).
Restart Delay
Set a delay between auto restart with the Restart Delay strategy:
CLI:
$ pm2 start app.js --restart-delay=3000
Via configuration file, use the restart_delay
attribute:
module.exports = {
script: 'app.js',
restart_delay: 3000
}
No Auto Restart
This is useful in case we wish to run 1-time scripts and don’t want the process manager to restart our script in case it’s completed running.
CLI:
$ pm2 start app.js --no-autorestart
Via configuration file, use the autorestart
attribute:
module.exports = {
script: 'app.js',
autorestart: false
}
Skip Auto Restart For Specific Exit Codes
Sometimes you might want the application to automatically restart in case of failure (i.e. non-zero exit code),
while not wanting the process manager to restart it when it shuts down properly (i.e. exit code equal to 0).
In this case, you can still use PM2 just fine with a stop_exit_codes
option set to exit codes that should skip auto restart:
CLI:
$ pm2 start app.js --stop-exit-codes 0
Or via configuration file, use the stop_exit_codes
attribute:
module.exports = [{
script: 'app.js',
stop_exit_codes: [0]
}]
Exponential Backoff Restart Delay
A new restart mode has been implemented on PM2 Runtime, making your application restarts in a smarter way. Instead of restarting your application like crazy when exceptions happens (e.g. database is down), the exponential backoff restart will increase incrementally the time between restarts, reducing the pressure on your DB or your external provider… Pretty easy to use:
CLI:
$ pm2 start app.js --exp-backoff-restart-delay=100
Via configuration file, use the exp_backoff_restart_delay
attribute:
module.exports = {
script: 'app.js',
exp_backoff_restart_delay: 100
}
When an application crash unexpectedly and the option --exp-backoff-restart-delay
is activated, you will be able to see a new application status waiting restart.
By running pm2 logs
you will also see the restart delay being incremented:
PM2 | App [throw:0] will restart in 100ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 150ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 225ms
As you can see the restart delay between restarts will increase in an exponential moving average, till reaching the maximum of 15000ms between restarts.
When the application will then get back to a stable mode (uptime without restarts of more than 30 seconds), the restart delay will automatically reset to 0ms.
Contribute to this page
I have a Node.js app ready which is workable, but has known and unknown bugs which crash the app. In such cases it would be nice if pm2
can restart the node app. Is this feature already available in pm2
?
asked Oct 1, 2014 at 6:29
Talespin_KitTalespin_Kit
20.6k29 gold badges89 silver badges131 bronze badges
Yes, it does this by default. For more information see Restart strategies.
If the app repeatedly fails to start over a short period of time, pm2 may cease restarting. See configuration, min_uptime
and max_restarts
.
answered Oct 1, 2014 at 6:57
14
Also, check this new excellent option:
--exp-backoff-restart-delay=100
pm2
will restart the crashed app after 100 milliseconds (0.1 seconds), then step-by-step increase restart-delay to 15 seconds.
answered May 7, 2019 at 12:55
xoidxoid
1,1041 gold badge10 silver badges24 bronze badges
To make app restart when it crashes you have to use one of PM2’s restart strategies.
There is something called «Exponential Backoff Restart Delay» which PM2 explains as:
Instead of restarting your application like crazy when exceptions happens (e.g. database is down), the exponential backoff restart will increase incrementaly the time between restarts.
You can set it using the CLI like this:
pm2 start app.js --exp-backoff-restart-delay=100
There are other restart methods also, which are mentioned here.
answered Mar 24, 2020 at 10:14
illiteratewriterilliteratewriter
4,0951 gold badge22 silver badges43 bronze badges
This may help:
# Generate Startup Script
$ pm2 startup
# Freeze your process list across server restart
$ pm2 save
# Remove Startup Script
$ pm2 unstartup
More details here
answered Oct 9, 2019 at 14:48
AlliswellAlliswell
1,51320 silver badges35 bronze badges
Exponential Backoff Restart Delay
Available in PM2 >= 3.2
A new restart mode has been implemented on PM2 Runtime, making your application restarts in a smarter way. Instead of restarting your application like crazy when exceptions happens (e.g. database is down), the exponential backoff restart will increase incrementaly the time between restarts, reducing the pressure on your DB or your external provider… Pretty easy to use:
CLI:
$ pm2 start app.js --exp-backoff-restart-delay=100
Or via ecosystem.config.js file:
module.exports = [{
script: 'app.js',
exp_backoff_restart_delay: 100
}]
When an application crash unexpectedly and the option --exp-backoff-restart-delay
is activated, you will be able to see a new application status waiting restart.
By running pm2 logs
you will also see the restart delay being incremented:
PM2 | App [throw:0] will restart in 100ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 150ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 225ms
As you can see the restart delay between restarts will increase in an exponential moving average, till reaching the maximum of 15000ms between restarts.
When the application will then get back to a stable mode (uptime without restarts of more than 30 seconds), the restart delay will automatically reset to 0ms.
Fixed Restart Delay
Available in PM2 >= 0.9
You can also use the restart_delay
to set a fixed timing between restarts:
CLI:
$ pm2 start app.js --restart-delay=3000
Or via ecosystem.config.js file:
module.exports = [{
script: 'app.js',
restart_delay: 3000
}]
Memory based reload strategy
Checkout https://pm2.io/docs/docs/runtime/features/memory-limit/
0second Downtime Reload
Checkout the cluster mode to get this behavior
No Auto Restart
This is useful in case we wish to run 1-time scripts and don’t want the process manager to restart our script in case it’s completed running.
Simply running these scripts from bash would terminate the script in case the ssh-session is terminated and the script should not get restarted when it completes execution.
PM2 is perfect for such cases, providing robust monitoring and logging
CLI:
$ pm2 start app.js --no-autorestart
In this article, we are going to learn, about restarting a Node.js application when an uncaught exception happens. For this, we are going to use the pm2 module.
Approach: Let’s see the approach step by step:
- Step 1: Install the pm2 module and use it to start the server.
- Step 2: When an uncaught exception happens, then execute the command process.exit() to stop the server.
- Step 3: Then, pm2 module will automatically start the server again.
process.exit() stop the server and pm2 force it to start. In this way, the server will restart.
Implementation: Below is the step-by-step implementation of the above approach.
Step 1: Initializes NPM: Create and Locate your project folder in the terminal & type the command
npm init -y
It initializes our node application & makes a package.json file.
Step 2: Install Dependencies: Locate your root project directory into the terminal and type the command
npm install express pm2
To install express and pm2 as dependencies inside your project
Step 3: Creating a list of products: Let’s create an array of products and set it to constant products.
const products = [];
Step 4: Creating Routes for the home page and the products page: Let’s create two routes so that users can access the home page and the products page.
app.get('/', (req, res) => { res.send('Hello Geeks!'); }); app.get('/products', (req, res) => { if (products.length === 0) { res.send('No products found!'); process.exit(); } else { res.json(products); } });
Inside the product route, we use process.exit() method to stop the server.
Complete Code:
Javascript
const express = require(
'express'
);
const app = express();
const products = [];
app.get(
'/'
, (req, res) => {
res.send(
'Hello Geeks!'
);
});
app.get(
'/products'
, (req, res) => {
if
(products.length === 0) {
res.send(
'No products found!'
);
process.exit();
}
else
{
res.json(products);
}
});
app.listen(3000, ()=>{
console.log(
'listening on port 3000'
);
});
Steps to run the application: Inside the terminal type the command to run your script ‘app.js’ with pm2.
pm2 start app.js
Output:
Last Updated :
18 Jul, 2022
Like Article
Save Article
Restart strategies
When starting application with PM2, application are automatically restarted on auto exit, event loop empty (node.js) or when application crash.
But you can also configure extra restart strategies like:
- Restart app at a specified CRON time
- Restart app when files have changed
- Restart when app reach a memory threshold
- Delay a start and automatic restart
- Disable auto restart (app are always restarted with PM2) when crashing or exiting by default)
- Restart application automatically at a specific exponential increasing time
Restart at cron time
Via CLI:
$ pm2 start app.js --cron-restart="0 0 * * *"
# Or when restarting an app
$ pm2 restart app --cron-restart="0 0 * * *"
Via configuration file, use the cron_restart
attribute:
module.exports = {
apps : [{
name: 'Business News Watcher',
script: 'app.js',
instances: 1,
cron_restart: '0 0 * * *',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
}
To disable cron restart:
pm2 restart app --cron-restart 0
Restart on file change
PM2 can automatically restart your application when a file is modified in the current directory or its subdirectories:
Via CLI:
$ pm2 start app.js --watch
Note: If an application is started with the --watch
option, stopping the app will not prevent it to be restarted on file change.
To totally disable the watch feature, do: pm2 stop app --watch
or toggle the watch option on application restart via pm2 restart app --watch
.
Via configuration file, use the watch: true
attribute:
module.exports = {
script: "app.js",
watch: true
}
You can specify which folder to watch for change, ignore folder and watch files interval with these options:
module.exports = {
script: "app.js",
// Specify which folder to watch
watch: ["server", "client"],
// Specify delay between watch interval
watch_delay: 1000,
// Specify which folder to ignore
ignore_watch : ["node_modules", "client/img"],
}
Memory based restart strategy
PM2 allows to reload (auto fallback to restart if not in cluster) an application based on a memory limit/ Please note that the PM2 internal worker (which checks memory), starts every 30 seconds, so you may have to wait a bit before your process gets restarted automatically after reaching the memory threshold.
CLI:
$ pm2 start api.js --max-memory-restart 300M
Via configuration file, use the max_memory_restart
attribute:
module.exports = {
script: 'api.js',
max_memory_restart: '300M'
}
Note: Units can be K(ilobyte) (e.g. 512K
), M(egabyte) (e.g. 128M
), G(igabyte) (e.g. 1G
).
Restart Delay
Set a delay between auto restart with the Restart Delay strategy:
CLI:
$ pm2 start app.js --restart-delay=3000
Via configuration file, use the restart_delay
attribute:
module.exports = {
script: 'app.js',
restart_delay: 3000
}
No Auto Restart
This is useful in case we wish to run 1-time scripts and don’t want the process manager to restart our script in case it’s completed running.
CLI:
$ pm2 start app.js --no-autorestart
Via configuration file, use the autorestart
attribute:
module.exports = {
script: 'app.js',
autorestart: false
}
Skip Auto Restart For Specific Exit Codes
Sometimes you might want the application to automatically restart in case of failure (i.e. non-zero exit code),
while not wanting the process manager to restart it when it shuts down properly (i.e. exit code equal to 0).
In this case, you can still use PM2 just fine with a stop_exit_codes
option set to exit codes that should skip auto restart:
CLI:
$ pm2 start app.js --stop-exit-codes 0
Or via configuration file, use the stop_exit_codes
attribute:
module.exports = [{
script: 'app.js',
stop_exit_codes: [0]
}]
Exponential Backoff Restart Delay
A new restart mode has been implemented on PM2 Runtime, making your application restarts in a smarter way. Instead of restarting your application like crazy when exceptions happens (e.g. database is down), the exponential backoff restart will increase incrementally the time between restarts, reducing the pressure on your DB or your external provider… Pretty easy to use:
CLI:
$ pm2 start app.js --exp-backoff-restart-delay=100
Via configuration file, use the exp_backoff_restart_delay
attribute:
module.exports = {
script: 'app.js',
exp_backoff_restart_delay: 100
}
When an application crash unexpectedly and the option --exp-backoff-restart-delay
is activated, you will be able to see a new application status waiting restart.
By running pm2 logs
you will also see the restart delay being incremented:
PM2 | App [throw:0] will restart in 100ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 150ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 225ms
As you can see the restart delay between restarts will increase in an exponential moving average, till reaching the maximum of 15000ms between restarts.
When the application will then get back to a stable mode (uptime without restarts of more than 30 seconds), the restart delay will automatically reset to 0ms.
Contribute to this page
Exponential Backoff Restart Delay
Available in PM2 >= 3.2
A new restart mode has been implemented on PM2 Runtime, making your application restarts in a smarter way. Instead of restarting your application like crazy when exceptions happens (e.g. database is down), the exponential backoff restart will increase incrementaly the time between restarts, reducing the pressure on your DB or your external provider… Pretty easy to use:
CLI:
$ pm2 start app.js --exp-backoff-restart-delay=100
Or via ecosystem.config.js file:
module.exports = [{
script: 'app.js',
exp_backoff_restart_delay: 100
}]
When an application crash unexpectedly and the option --exp-backoff-restart-delay
is activated, you will be able to see a new application status waiting restart.
By running pm2 logs
you will also see the restart delay being incremented:
PM2 | App [throw:0] will restart in 100ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 150ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 225ms
As you can see the restart delay between restarts will increase in an exponential moving average, till reaching the maximum of 15000ms between restarts.
When the application will then get back to a stable mode (uptime without restarts of more than 30 seconds), the restart delay will automatically reset to 0ms.
Fixed Restart Delay
Available in PM2 >= 0.9
You can also use the restart_delay
to set a fixed timing between restarts:
CLI:
$ pm2 start app.js --restart-delay=3000
Or via ecosystem.config.js file:
module.exports = [{
script: 'app.js',
restart_delay: 3000
}]
Memory based reload strategy
Checkout https://pm2.io/docs/docs/runtime/features/memory-limit/
0second Downtime Reload
Checkout the cluster mode to get this behavior
No Auto Restart
This is useful in case we wish to run 1-time scripts and don’t want the process manager to restart our script in case it’s completed running.
Simply running these scripts from bash would terminate the script in case the ssh-session is terminated and the script should not get restarted when it completes execution.
PM2 is perfect for such cases, providing robust monitoring and logging
CLI:
$ pm2 start app.js --no-autorestart
use PM2 launch application When, the application will restart automatically when it exits automatically, the event loop is empty (node.js), or the application crashes. However, you can also configure additional restart policies, such as:
- Restart the application using a scheduled task
- Restart the application after the file changes
- Restart when application reaches memory threshold
- Delayed start and automatic restart
- By default, automatic restart is disabled on crash or exit (applications always restart using PM2)
- Automatically restart applications at specific exponential growth times
Restart the application using a scheduled task
Use the following command to set the task of scheduled restart
$ pm2 start server.js --cron-restart="0 0 * * *" # Or set a scheduled task when restarting $ pm2 restart app --cron-restart="0 0 * * *"
If yes configuration file If so, use cron_restart attribute:
server.config.js
module.exports = { apps : [{ name: 'server', script: 'server.js', instances: 1, cron_restart: '0 0 * * *', env: { NODE_ENV: 'development' }, env_production: { NODE_ENV: 'production' } }] }
Automatically restart the application after file changes
When the files in the current directory or its subdirectory are modified, PM2 can automatically restart your application:
Use the following command to start the application by specifying the option — watch later
$ pm2 start server.js --watch
Let’s illustrate this situation through gif dynamic diagram
Note: if the application starts using the – watch option, stopping the application does not prevent it from restarting when the file changes. To completely disable the watch function, execute the following command:
$ pm2 stop app --watch
Or use the following command to switch the watch option when the application restarts.
$ pm2 restart app --watch
In the configuration file, use the watch: true attribute
module.exports = { script: "server.js", watch: true }
We can also specify which folder to listen to in the configuration file, and automatically restart the application when its contents are modified. You can also specify that some folders are ignored, and no restart will be triggered regardless of how their contents change
module.exports = { script: "server.js", // Specify the folder to listen to watch: ["server", "client"], // Specify delay time watch_delay: 1000, // Specify the folder to ignore ignore_watch : ["node_modules", "client/img"], }
Restart when application reaches memory threshold
PM2 allows applications to be reloaded according to the memory limit (if they are not in the cluster, they will automatically fall back and restart) / please note that PM2 internal working program (check memory) starts every 30 seconds, so it may take a moment after reaching the memory threshold, and the process will restart automatically.
Use the — Max memory restart option to specify the memory threshold.
$ pm2 start server.js --max-memory-restart 300M
Use Max in configuration file_ memory_ Restart attribute.
server.config.js
module.exports = { script: 'server.js', max_memory_restart: '300M' }
Note: the units can be K(ilobyte) (e.g. 512K), m (egabyte) (e.g. 128M), G (igabyte) (e.g. 1G).
Delayed restart
Use the Restart Delay policy to set the delay between automatic restarts:
$ pm2 start server.js --restart-delay=3000
In the configuration file, use restart_ The delay property sets delayed restart.
server.config.js
module.exports = { script: 'server.js', restart_delay: 3000 }
Prohibit automatic restart
This is useful if we want to run the script once and do not want the process manager to restart our script when the script finishes running.
$ pm2 start server.js --no-autorestart
In the configuration file, use the autorestart: false attribute to disable automatic restart.
server.config.js
module.exports = { script: 'server.js', autorestart: false }
Specifies an exit code that does not restart automatically
Sometimes we may want the application to restart automatically in the event of a failure (that is, a non-zero exit code) rather than the process manager to restart it when it closes properly (that is, the exit code is equal to 0).
In this case, PM2 can still be used well and stop_ exit_ The codes option is set to the exit code that should skip automatic restart:
$ pm2 start server.js --stop-exit-codes 0
In the configuration file, use stop_ exit_ The codes property sets the exit code without automatic restart.
server.config.js
module.exports = [{ script: 'server.js', stop_exit_codes: [0] }]
Exponential backoff restart delay
A new restart mode has been implemented on PM2 Runtime to restart our applications in a more intelligent way. When an exception occurs (such as database shutdown), instead of restarting the application crazily, exponential backoff restart will increase the time between restarts and reduce the pressure on our database or external providers… Very easy to use:
Set this function on the terminal command line with the option — exp backoff restart delay
$ pm2 start app.js --exp-backoff-restart-delay=100
In the configuration file, use exp_backoff_restart_delay property.
server.config.js
module.exports = { script: 'server.js', exp_backoff_restart_delay: 100 }
When the application crashes unexpectedly and the option — exp backoff restart delay is activated, we will be able to see the new application state waiting restart.
By running pm2 logs , we will also see an increase in restart latency:
PM2 | App [throw:0] will restart in 100ms PM2 | App [throw:0] exited with code [1] via signal [SIGINT] PM2 | App [throw:0] will restart in 150ms PM2 | App [throw:0] exited with code [1] via signal [SIGINT] PM2 | App [throw:0] will restart in 225ms
As you can see, the restart delay between restarts will increase exponentially until the maximum value between restarts is 15000 milliseconds.
When the application returns to stable mode (uptime does not exceed 30 seconds), the restart delay will automatically reset to 0 milliseconds.
For more information about pm2, refer to pm2 tutorial
Для обеспечения непрерывной работоспособности Node.js сервера нужно либо постоянно держать открытой консоль, либо использовать менеджер процессов pm2. Он имеет встроенный балансировщик нагрузки, позволяет следить за потребляемыми ресурсами запущенных процессов, автоматически перезапускать процессы после системного сбоя и т. д.
Менеджер процессов pm2
имеется в репозитории npm и должен быть установлен в системе глобально.
Управление процессами¶
Запуск Node.js сервера с использованием pm2
осуществляется командой start
, которой передается путь к главному файлу приложения.
Команда start
инициирует запуск приложения в фоновом режиме и добавляет его в список процессов, который можно увидеть выполнив команду ls
.
Перечень полей таблицы:
app name
— имя приложения (по умолчанию имя главного файла без расширения), для задания собственного названия используйте при запуске параметр--name
:pm2 start app.js --name=custom_app_name
id
— уникальный идентификатор приложения;mode
— режим, в котором был запущен сервер (fork
илиcluster
);pid
— уникальный идентификатор процесса в системе;status
— статус приложения, может бытьlaunching
,online
,errored
илиstopped
;restart
— количество перезапусков;uptime
— время, прошедшее с момента запуска приложения;cpu
— нагрузка на процессор в процентах;mem
— занимаемая приложением оперативная память.
Для получения более подробной информации о количестве запросов, параметрах запуска процессов и т. д. используйте команду monit
.
За перезапуск процесса отвечает команда restart
, принимающая имя или идентификатор приложения.
Выполнение restart
увеличивает значение одноименного поля в списке процессов применительно к тому из них, для которого была выполнена команда.
Остановка процесса осуществляется командой stop
, которой необходимо указать либо название, либо идентификатор приложения.
Выполнение stop
останавливает работу приложения, но не удаляет его из списка процессов, статус при этом будет stopped
.
Чтобы остановить процесс и удалить его из списка, используйте команду delete
.
Посмотреть консольные логи приложения можно командой log
. Если для log
не указать приложение, то будут выведены логи всех процессов, отсортированные по времени.
Командам restart
, stop
, delete
и log
можно передать через пробел сразу несколько процессов для обработки.
pm2 delete app1 app2 app3
Для возможности восстановления и запуска списка процессов в случае перезапуска или непредвиденного сбоя сервера, сохраните текущую конфигурацию на диск выполнив команду save
.
После этого сохраненные процессы могут быть запущены следующим образом.
Распределение нагрузки (кластеризация)¶
Запуск приложения в нескольких экземплярах, которые будут распределять между собой поступающие запросы, осуществляется с использованием параметра -i
(instances) у команды start
, с помощью которого указывается, сколько экземпляров запустить. Создание дополнительных процессов одного и того же приложения называется кластеризацией.
Приведенная команды запускает приложение в двух экземплярах. Помните, что для эффективной работы кластера количество дополнительных процессов не должно превышать количество ядер процессора. Чтобы запустить количество процессов равное количеству ядер, укажите параметру -i
значение max
.
В данном случае Node.js pm2
самостоятельно определит количество ядер процессора и создаст соответствующее количество дополнительных экземпляров.
Файл ecosystem.config.js¶
Если разработанная вами система состоит из множества приложений, которым к тому же при запуске необходимо указывать массу параметров, то при развертывании на разных серверах этот процесс займет немало времени. Чтобы оптимизировать все это, в pm2
имеется поддержка запуска приложений из конфигурационного файла — ecosystem.config.js
.
Чтобы сгенерировать шаблон ecosystem.config.js
воспользуйтесь следующей командой.
Теперь в директории, откуда была выполнена команда, должен появиться файл ecosystem.config.js
с таким содержимым.
ecosystem.config.js
module.exports = {
apps: [
{
name: 'app',
script: './app.js',
env: {
NODE_ENV: 'development',
},
env_production: {
NODE_ENV: 'production',
},
},
],
};
В массиве apps
каждый элемент является объектом, описывающим конфигурацию для запуска одного приложения набором параметров. Рассмотрим основные из них:
name
— имя приложения, которое будет отображаться в списке процессов при выполнении командыpm2 list
;script
— путь к главному файлу приложения, который отвечает за запуск;instances
— запускает процесс в кластерном режиме, в качестве значения передается количество дополнительных экземпляров;disable_logs
— если задатьtrue
, то логи вестись не будут;env
— значение переменной среды окруженияNODE_ENV
в режиме разработки;env_production
— значение переменной среды окруженияNODE_ENV
в режиме эксплуатации.
ПС полным списком параметров можно ознакомиться в официальной документации.
Для запуска описанных в ecosystem.config.js
приложений, выполните команду start
с указанием пути к файлу.
pm2 start ecosystem.config.js
Если вам нужно запустить только одно приложение из описанного массива, укажите параметр --only
и значение поля name
из конфигурации.
pm2 start ecosystem.config.js --only my-app
Лимит использования RAM¶
Менеджер процессов Node.js pm2 позволяет настроить перезапуск процесса по достижению использования им указанного объема оперативной памяти. Для этого при запуске приложения необходимо указать параметр --max-memory-restart
.
pm2 start index.js --max-memory-restart 150M
Значение параметра указывается в одном из трех возможных измерений:
K
(килобайты);M
(мегабайты)G
(гигабайты).
Проверка использования процессами оперативной памяти осуществляется pm2 раз в 30 секунд.
Детектирование изменений¶
В pm2 также можно настроить автоматический перезапуск приложения при изменении одного из его файлов. Для этого при старте приложения укажите параметр --watch
.
pm2 start index.js --watch
Процесс отслеживания изменений не завершается с остановкой процесса приложения. Чтобы отключить его, при выполнении команды stop
также необходимо передать параметр --watch
.
Параметр --watch
имеет ряд параметров, но их указание возможно только через файл ecosystem.config.js
.
ecosystem.config.js
module.exports = {
apps: [
{
name: 'my-app',
script: './index.js',
watch: ['server'],
ignore_watch: ['node_modules', 'client'],
watch_delay: 1000,
},
],
};
Здесь в параметре watch
явно указывается, изменений каких директорий необходимо отслеживать. Чтобы исключить из отслеживания определенные директории, имеется параметр ignore_watch
. А с помощью watch_delay
указывается время в миллисекундах, которое необходимо выждать при перезапуске приложения, прежде чем инициировать процесс детектирования изменений.
Буквально пару часов назад у меня завязался спор на тему того, что Node.JS слишком медленная для крупных проектов и ей стоит предпочесть Golang, Rust, PHP, etc. Основным аргументом противоположной стороны в этом споре был факт однопоточности JavaScript. Якобы при разработке приложения производительность просто упрётся в эту однопоточность и ничего сделать уже нельзя — только переписать на каком-то другом языке. Однако дела с этим в NodeJS обстоят немного лучше, чем кажется на первый взгляд. Перед тем, как мы углубимся в эту тему хочу заявить, что уважаю право каждого разработчика использовать тот язык программирования, который пришёлся ему по душе и который он считает предпочтительным в той или иной задаче.
Сделав поиск по ключевому слову «PM2» на Хабре я не нашёл ни одной статьи, посвящённой этому process-менеджеру. Лишь одиночные упоминания в статьях других пользователей. Я загорелся (сильно сказано) идеей наверстать упущенное и пролить свет на этот тёмный уголок разработки backend на Node.JS (о котором многие знают, да, я в курсе). Всех заинтересовавшихся прошу под кат.
PM2 — это менеджер процессов с открытым исходным кодом, распространяющийся под лицензией AGPL-3.0. В момент написания статьи имеет ~350k загрузок в неделю, согласно данным NPM. В основном применяется в средах, где необходимо запустить приложение на NodeJS и забыть о нём (с остальными языками тоже можно использовать, но об этом позднее), позволяющий кластеризировать приложение и гибко распределять нагрузку между ядрами процессора. Небольшая вырезка из репозитория PM2 на GitHub:
PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.
Многие новички при разработке сталкиваются с проблемой, когда после «выкатки» приложения на production сервер, не знают как запустить его «навечно». Пишут в SSH-консоли set NODE_ENV=production && node app.js
, всё отлично, приложение работает. Закрывают консоль и приложение больше не работает. Вопрос на StackOverflow — How to run node.js application permanently? набрал более 237 тыс. просмотров за всё время.
PM2 решает эту проблему одной командой:
pm2 start app.js
Эта команда «демонизирует» (от англ. «daemonize») процесс NodeJS, следит за потреблением им памяти и считает нагрузку на процессор.
Вернёмся к нашим баранам
С ростом нагрузки на backend возникает необходимость его масштабирования — как вертикального, так и горизонтального — кому что удобнее в сложившихся обстоятельствах. Как мы знаем, один процесс может использовать несколько ядер процессора, но только в том случае, если внутри процесса имеется несколько потоков. В NodeJS приложениях поток — один. PM2 способен выручить в этой ситуации и распределить нагрузку между несколькими ядрами процессора. По-прежнему всего с одной командой:
pm2 start app.js -i max
В данном случае параметр max соответствует количеству ядер процессора. Т.е. для 8-ядерного процессора будет создано 8 отдельных процессов. Можно также вместо max задать значение -1 и тогда количество процессов будет соответствовать количество_ядер минус 1. Вся прелесть заключается в том, что и HTTP(S)/Websocket/TCP/UDP соединения будут равномерно распределены между этими процессами. Ну чем не горизонтальное масштабирование? Почитать подробнее о кластеризации в PM2 можно по ссылке — PM2 Cluster Mode.
Вы можете запустить сколько угодно процессов, но всё же рекомендуется придерживаться рекомендации «один процесс на одно ядро».
Бережное отношение к памяти
При разработке на PHP я однажды столкнулся с проблемой. По неопытности неосознанно заложил в движок системы баг, из-за которого при определённых условиях процессы начинали поедать слишком много оперативной памяти. Вдобавок к этому нагружался процессор, из-за чего виртуальная машина просто зависла и у меня не было к ней доступа совсем.
Как знают PHP-разработчики, в PHP-FPM можно задать тип распределения процессов (если вы вдруг не знали, то в PHP-FPM для каждого нового запроса создаётся новый процесс) — статический, когда задаётся минимальный и максимальный порог, и динамический — выделение сколь угодно большого количества процессов, по необходимости. Что будет в PM2, если запустить 8 процессов и все они начнут потреблять много памяти? И эту проблему PM2 в состоянии решить — лишь одним параметром в командной строке:
# Set memory threshold for app reload
pm2 start app.js -i max --max-memory-restart <200MB>
Каждый раз при достижении лимита по памяти PM2 автоматически перезапустит процесс. Распределять память проще чем процессы, не так ли? 8 процессов * 200 мегабайт = 1,6 гигабайт. Математика уровня второго класса.
Помимо перезапуска процесса можно также настроить и перезапуск через N интервал времени. Я пока не придумал в каких случаях это может пригодиться, но не стесняйтесь указать мне на пару примеров в комментариях
А если я перезагружу виртуальную машину?
Сюрприз-сюрприз! Эту проблему PM2 тоже решает за вас. Всё ещё не более чем одной единственной командой в консоли:
pm2 startup
PM2 сгенерирует скрипт, который будет поднимать все необходимые процессы при запуске операционной системы. Однако здесь стоит быть бдительным — при обновлении версии Node.JS всё может сломаться. Во избежание этого, после успешного обновления до новой версии Node.JS выполните pm2 unstartup
и pm2 startup
. Подробнее об этом можно ознакомиться по ссылке — PM2 Startup Script Generator.
А надо ли перезапускать кластеры вручную при внесении изменений?
Конечно же нет! Ну, точнее, вы, конечно, можете перезапускать приложение вручную, но зачем? Автоматизируйте всё что можете и да прибудет с вами сила!
pm2 start env.js --watch --ignore-watch="node_modules"
Вы можете пользоваться этим при слиянии master-ветки в локальном репозитории с master-веткой из удалённого репозитория. В моём сайд-проекте это делается просто — git pull origin master && npm run build
. При изменении файлов в папках server/build и client/build процессы будут автоматически перезапущены. Я понимаю, это очень простенькая фича и она не заслуживает даже быть упомянутой в этом тексте. Разбавлю его кое-чем серьёзным и напишу о том, что если вы пользуетесь кластеризацией, то все процессы будут перезагружены поочерёдно. Да так, что как минимум один из них будет всегда доступен. Это же zero-downtime deployment!
А можно и не перезапускать процессы. Для этого есть reload (нечто похожее на nginx reload):
pm2 reload all
Слишком много команд! И вообще я предпочитаю конфиги
Мне уже наскучило придумывать весёлые фразы, поэтому просто и банально: файл экосистемы — есть. Поддерживаются форматы JSON, YAML и JS. Например, когда необходимо следить за файлами в папках server и client:
module.exports = {
apps: [{
script: "app.js",
watch: ["server", "client"],
env_production : {
"NODE_ENV": "production"
}
}]
}
Подробнее ознакомиться можно по ссылке — PM2 Application Declaration.
И даже мониторинг есть!
И не один. Выбирайте тот который нравится больше. Можно мониторить в консоли командой:
pm2 monit
Или же воспользоваться полноценной веб-версией мониторинга:
Вы мне, конечно же, не поверите, но она устанавливается и запускается одной командой:
pm2 plus
И многое-многое другое…
Заявлена поддержка Heroku и Docker, автоматическое инкрементирование портов с возможностью передачи в process.env
(когда нужно каждый процесс запускать на отдельном порту), запуск нескольких инстансов PM2 в пределах одной ОС, наличие программного API и возможность запускать демонизированные Bash и Python скрипты!
Вероятно, я упустил ещё что-то важное или интересное, о чём всегда можно напомнить мне в комментариях. Надеюсь, что вы смогли почерпнуть для себя что-то новое из этой статьи.
В этой статье я расскажу о самом удобном, на мой взгляд, диспетчере процессов. Покажу, как его установить и настроить свои проекты (например: скрипт для автопостинга, сервис на ReactJS).
PM2 запускает приложения и скрипты в режиме 24/7 и решает проблему с их вылетами путем автоматического перезапуска с сохранением лога. Это решение особенно полезно для тех, кто держит на своем сервере большое количество скриптов и нуждается в их удобном управлении.
Рассмотрим установку и настройку на примере Ubuntu 18.04.
Установка
Так как PM2 написан на Node.js и устанавливается с помощью npm, нужно установить их на свой виртуальный сервер:
sudo apt install nodejs sudo apt install npm
Теперь устанавливаем сам диспетчер процессов:
Готово! PM2 на сервере.
Комьюнити теперь в Телеграм
Подпишитесь и будьте в курсе последних IT-новостей
Подписаться
Настройка
PM2 в основном предназначен для приложений Node.js, но работает и с остальными языками программирования. Чтобы запустить приложение, используем команды в консоли.
Для Node.js:
Для остальных языков программирования (на примере Python 3):
pm2 start app_name.py --interpreter=python3
Если ваше приложение завершит работу с ошибкой, PM2 автоматически перезапустит его, что очень удобно.
После запуска скриптов и приложений можно посмотреть информацию о них с помощью команды в консоли:
Пример того, что мы увидим:
В таблице показано количество рестартов, потребляемая память и нагрузка на процессор от приложений.
Для удаления, запуска, рестарта и остановки приложений из списка нужно посмотреть порядковый номер (id) процесса в таблице, которую можно вызвать командой, указанной выше, и написать команды в консоли.
Остановка:
pm2 stop id
Запуск:
pm2 start id
Рестарт:
pm2 restart id
Удаление из списка:
pm2 delete id
Также можно просмотреть логи отдельных приложений. Для этого используем эту команду:
И выбираем свое приложение из списка.
Если вам неудобно следить за логами и запуском приложений через консоль, то это можно делать даже в браузере, установив веб-версию PM2 одной командой:
После этого вводим свои данные для регистрации и переходим по ссылке, которая отобразится в консоли.
Пример того, что мы увидим:
Мы разобрали основные команды менеджера процессов. Удачи в ваших проектах!