Scaling A Node JS Server For Performance
Tags: node, performance, cluster, worker
Published: 2021-10-11 14:09:34

When using NodeJS one is likely to quickly run into scaling problems as compared to other programming language. This is a good thing as it allows you to make adjustment earlier on how to scale your application.
NodeJS is single threaded and it only runs your code using a solitary cpu of your hardware. Forking your application into multiple instances enables your application to take advantage of your hardware. NodeJS achieves this by using the cluster module that bundles with it. A cluster is made up of workers process that is controlled by the main process that runs different instances of your application. 
One of the main advantages of running different processes is that your application never has a down time. When a single process fails the main process can automatically restart the failed worker process.

Let us create a small app that shows how we can make use of the cluster module to create different instances of our app

````javascript
  const cluster = require("cluster");
  const http = require("http");
  //importing the necessary module
````
````javascript
  //lets create a http server to serve a request from our 
  server.The server will respond with a random quote from an 
  array

  const quotes = [
     "The journey of a thousand miles begins with one step",
     "That which does not kill us makes us stronger",
     "Life is what happens when you’re busy making other 
     plans",
    "When the going gets tough, the tough get going",
    "You only live once, but if you do it right, once is 
     enough",
    "You must be the change you wish to see in the world.",
    "Get busy living or get busy dying",
   "It is better to have loved and lost than to have never 
    loved at all.",
];
  
  http.createServer((req, res) => {
     const index = Math.floor(Math.random() * quotes.length)
     res.end(quotes[index]);
  }).listen(3000)

```` 
 This is a simple server that handles and responds back to the client a random quote. This application can be made to make use of the cluster module for creating different instance of it.
````javascript
const http = require("http")
const cluster = require("cluster");
const os = require("os");

const quotes = [
     "The journey of a thousand miles begins with one step",
     "That which does not kill us makes us stronger",
     "Life is what happens when you’re busy making other 
     plans",
    "When the going gets tough, the tough get going",
    "You only live once, but if you do it right, once is 
     enough",
    "You must be the change you wish to see in the world.",
    "Get busy living or get busy dying",
   "It is better to have loved and lost than to have never 
    loved at all.",
];

//this code gets the number of cpu in the system
const cpu = os.cpus().length;
if (cluster.isMaster) {
//this is the main process here

//this forloop creates worker processs to run the application 
//according to the number of cpu we have in the system.
for (let i = 0; i < cpu; i++) {
    //creates a new worker process
    cluster.fork();
  }
//the exit event is called when a worker dies with the worker pass as an arguments to the callback function.

cluster.on("exit", (worker) => {
  //lets recreate the worker that died
   cluster.fork();
});
} 
else {
  //this is the worker process where we create our server to 
  //handle the quote sending
     http.createServer((req, res) => {
  //get random quotes
  const index = Math.floor(Math.random() * quotes.length );
  res.end(`${quotes[index]}- handled by ${process.pid} `);
  console.log(`handled by ${process.pid}`);
}).listen(3000);

}

````
The cluster module implements the event emitter class and it is able to notify when a worker dies. The best way to scale our application in a production environment is to use a tool developed for that process.

One of such tool is the pm2 which can be installed globally via npm.

````javascript
  sudo npm install -g pm2
  //this install pm2 globally
````
Useful pm2 commands
````javascript
  //to start your application with a name of app.js
 pm2 start app.js -i -1
 //the above pm2 command creates an instance of the app.js code equivalent to the number of cpus on the server
pm2 stop app //to stop the app
pm2 delete app //to remove it from pm2
pm2 list // this creates a list of all the running instances of the application
pm2 logs //to view the application logs
pm2 monit //this opens up a monitor on the console to monitor the app
pm2 reload app.js //this reloads the app without any downtime. 
````
In conclusion, scaling your nodejs app is a necessity for optimal performance.

Thanks for reading..