Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Advanced Node.js Process Management With PM2

DZone's Guide to

Advanced Node.js Process Management With PM2

In this article, I provide an introduction to PM2, showing why it is such a valuable tool for managing Node.js applications.

· Web Dev Zone ·
Free Resource

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

If you've worked on any front-end applications recently, you have likely had some contact with a Node/Express application. What you may not be familiar with is how these applications are managed in production.

I recently had a project where I needed to set up a Node application on an AWS server. I needed a tool to solve the technical challenges of managing the Node processes and deploying the application in a very efficient manner.

I chose PM2, which is a handy process management tool for running Node.js applications in production environments. PM2 provides a simple command line interface that makes it easy to get started. This powerful Node module has tools for managing application processes, logging, and more.

In this article, I provide an introduction to PM2, showing why it is such a valuable tool for managing Node.js applications. By way of a reference example application, we show the basic features and commands for using PM2 and give examples of generating configuration files for both running and deploying applications.

Example Node.js Application

To get started, we need to create a very simple example application. Use the following commands to create a new folder for the example app:

$ mkdir pm2-example-app
$ cd pm2-example-app
$ npm init -y

This will generate a basic package.json file which we will want to update the main line to use app.js rather than index.js:

{
  "name": "pm2-example-app",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Next, install Express:

$ npm install express --save

And now that we are all set up we can add the code in a new file: app.js.

var express = require('express');
var app = express();

app.get('/', (req, res) => {
  console.log('GET /');
  res.send('Hello World!');
});

app.listen(3000, () => {
  console.log('Listening on port 3000');
});

And that is it for our example app. Now we can start showing how PM2 can be used.

PM2's Command Line Interface

We will start with a few of the basic commands from the CLI. To use PM2, you will need to install it globally through npm:

$ npm install -g pm2@latest

And then we will use pm2 start to start the application.

$ pm2 start app.js

PM2 will print out some information in your terminal about the process you just started. You can then use the process ID to manage the process. So since 2065 is the pid of the process I just started, I can manage it with the following commands:

$ pm2 stop 2065
$ pm2 restart 2065
$ pm2 reload 2065

Most of these commands should be pretty self-explanatory. The only difference between reload and restart is that reload will restart the process(es) with zero downtime.

Alternatively, you can specify all rather than pid to affect all current processes. For example, this command will remove all existing processes.

$ pm2 delete all

Cluster Mode

One of the most powerful features of PM2 is the ability to run in cluster mode. This will run Node processes across all available CPUs. This greatly increases your application's ability to handle traffic without having to change any code.

Running multiple Node processes across all the available CPUs acts like a load balancer. So, as long as you are using a server with more than one CPU available, then you are increasing the reliability.

Use the following command to start our example app in cluster mode:

$ pm2 start app.js -i max

Note that I have used max here as a parameter, which means PM2 will auto-detect the number of CPUs available. You can also pass a number as well if you want to limit the number of CPUs used.

You can see from my screenshot that I now have the example application running in 8 different processes. Let's monitor these processes with this command:

$ pm2 monit

This will bring up a dashboard listing all the processes currently running though PM2 along with some other metrics like current CPU and memory usage.

We can use the following command to simulate some traffic to our application:

curl -s "http://localhost:3000?[1-1000]"

This should cause our processes to log the GET requests in the Global logs on the monitoring dashboard.

You can also stream the logs with the following command:

$ pm2 logs

Generating a Configuration File

Up until now, we have been using the CLI to manually tell PM2 how to manage our processes. Ideally, when deploying this, we want to have a configuration file that will take care of automating this for us.

Generate the default configuration file using the following command:

$ pm2 ecosystem simple

PM2 generates a ecosystem.config.js file. Here is what it looks like:

module.exports = {
  apps : [{
    name   : "app1",
    script : "./app.js"
  }]
}

Now, this is a little basic, so let's fill this out a bit more.

module.exports = {
  apps : [{
    name        : "pm2-example-app",
    script      : "./app.js",
    watch       : true,
    instances   : 4,
    exec_mode   : "cluster",
    env: {
      "PORT": 3000,
      "NODE_ENV": "development"
    },
    env_staging : {
      "PORT": 80,
      "NODE_ENV": "staging"
    },
    env_production : {
      "PORT": 80,
      "NODE_ENV": "production"
    }
  }]
}

Now let's pause and break down what we just did here.

You will notice the property apps is an array of JavaScript objects. So, if you're in a situation where you have many Node applications that will be running on the same server, then they all can be controlled from the same ecosystem configuration.

The script is the same app script that we had used previously. Setting the watch property to true tells PM2 to watch for code changes and automatically reloads if there are any. Then the next two properties, instances and exec_mode, are for specifying the number of CPUs and cluster mode as we had discussed previously.

Then the other properties are for declaring different environment variables. By default, it will run with the env environment, and you can see we have designated that as our development environment. We have also added a staging environment and production environments.

To execute the application with these, we need to pass in an env parameter on start or restart.

$ pm2 start ecosystem.config.js --env staging
$ pm2 start ecosystem.config.js --env production

Deployments

PM2 can also be configured to handle deployments. Take a look at an example setup for a production deployment below. This would belong in the ecosystem config below the apps property.

"deploy" : {
  "production" : {
    "key"  : "/path/to/key.pem",  // path to the private key to authenticate
    "user" : "node",              // user used to authenticate
    "host" : "111.11.111.1",      // where to connect
    "ref"  : "origin/master",
    "repo" : "git@github.com:repo.git",
    "path" : "/var/www/production",
    "post-deploy" : "pm2 startOrRestart ecosystem.config.js --env production"
  },
}

So in order to set this up, you will need to tell PM2 the path to your .pem key file, the host server's IP address, and the username used for connecting to the host. ref refers to the Git branch required (usually master for production) and repo which is the path to the source code repository. path is the path on the host server where you want to deploy the source code.

Then lastly, post-deploy allows you to specify a command to run after the deployment is complete. What we have specified here will start or restart the processes to run within the production environment.

To execute deployments we would use the following command locally. This will handle cloning the latest Git repository code on the server host and then using PM2 to start or restart the Node processes.

$ pm2 deploy ecosystem.config.js production

Recap

We have covered quite a bit of ground here, so let's recap. We discussed what PM2 is and why it is such a valuable tool for managing Node.js applications. Then we covered the basic features and commands for using PM2 and also gave examples of generating configuration files for both running and deploying applications.

Thank you for following along and if you have a need to manage and deploy Node.js applications I hope you have learned a bit about using PM2 to make that process easier. To learn more about what else PM2 can do be sure to check out the project page here.

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

Topics:
process management ,javascript ,pm2 ,node.js ,web dev

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}