Run a NodeJS HTTP ExpressJS Server on Multiple CPU Cores

October 05, 2019 0 Comments

Run a NodeJS HTTP ExpressJS Server on Multiple CPU Cores

 

 

Run a NodeJS HTTP ExpressJS Server on Multiple CPU Cores

Introduction

A single instance of a Node.js application runs on only one thread and, therefore, doesn't take full advantage of multi-core systems. There will be times when you may want to launch a cluster of Node.js processes to utilize each CPU core on a local machine or production server.

This issue is especially important when dealing with APIs or an ExpressJS based HTTP server.

Luckily, Node.js has a core module named Cluster that will help us run a Node.js application using all the CPU cores on a machine.

In this article, our Node.js application will be an ExpressJS HTTP server that we'll create a unique instance for on each CPU core. By doing so, the HTTP server's throughput will increase since each additional CPU core instance will boost the number of possible simultaneous requests.

Let's get started!

Table of Contents

Create an Express HTTP Server

The first thing we need to do is get an HTTP server up and running. If you already have an ExpressJS server created and running, you can skip to the next section.

We'll use ExpressJS to quickly get a fast and minimalist server going. If you haven't already installed the npm package, you can do so with this command:

$ npm install --save express

Then, add this code the Node.js file you want to work with:

Node.js

const express = require("express")

const PORT = process.env.PORT || 5000

const app = express()

app.listen(PORT, function () {

  console.log(`Express server listening on port ${PORT}`)

})

First, we require() the Express npm package we installed earlier.

Then, we create a PORT variable that is either the current process.env.PORT value or 5000. And we create an instance of express using the express() method and hold it in the app variable.

The last thing we add is the app.listen() function to start the Express app and tell it to listen on the PORT we specified.

When you run the code via the command line, you should see this message or something similar logged to the console:

Output

Express server listening on port 5000

Awesome! We now have an Express HTTP server running.

Run the Server on Multiple Cores

In this section, we'll get our Express server running on multiple CPU cores!

To help us achieve that, we'll be using the OS and Cluster Node.js modules. We'll use the OS module to detect how many CPU cores the system has and the Cluster module to create multiple children processes our HTTP server can run on in parallel.

Since these are core modules, we don't need to install any npm packages and we can require() them into our code right away.

We're going to give you the full code upfront and explain everything afterward, so don't panic if you don't understand everything at first glance.

Here's the full code:

Node.js

const express = require("express")

const os = require("os")

const cluster = require("cluster")

const PORT = process.env.PORT || 5000

const clusterWorkerSize = os.cpus().length

if (clusterWorkerSize > 1) {

  if (cluster.isMaster) {

    for (let i=0; i < clusterWorkerSize; i++) {

      cluster.fork()

    }

    cluster.on("exit", function(worker) {

      console.log("Worker", worker.id, " has exitted.")

    })

  } else {

    const app = express()

    app.listen(PORT, function () {

      console.log(`Express server listening on port ${PORT} and worker ${process.pid}`)

    })

  }

} else {

  const app = express()

  app.listen(PORT, function () {

    console.log(`Express server listening on port ${PORT} with the single worker ${process.pid}`)

  })

}

A lot is going on in the code, so let's go through each part.

The first thing we do is require() the express npm package and the two Node.js core modules os and cluster.

Next, we create a PORT variable and assign it either the value of the current process.env.PORT number or 5000. We'll use this later on when we start the express application.

Then we create a variable called clusterWorkerSize to represent the number of CPUs the system has. We use the os.cpus().length method to get that number. Check out the Node.js documentation for more info on the os.cpus() method.

Using the clusterWorkerSize value, we create an if...else statement that checks whether or not the system has more than one CPU core. If the number of CPUs is greater than 1, we move on with creating the cluster. But if there is only one CPU on the machine the code is running on, we start the Express application the same way we did in the first step of this tutorial.

Assuming our machine has more than one CPU, the first thing we do is create another if...else statement that checks whether or not this is the first process in the cluster that has run. We check that with the cluster.isMaster() method that returns either true or false.

If that is the first process that has run, we use cluster.fork() to spawn a new worker process for each of the CPU's that exist on the machine. And we also add an event listener that will log a message when a worker exits so we know when something goes wrong or unexpected.

It's also worth noting that the master process listens at our HTTP server's port and load balances all requests among the workers.

Once all our workers are spawned, we create a new instance of our express app on each of the workers we created. If your machine has 2 CPU cores, 2 instances of the application will be created.

When you run the application, you should see this or something similar logged to the console:

Output

Express server listening on port 5000 and worker 10801

Express server listening on port 5000 and worker 10802

Express server listening on port 5000 and worker 10803

Express server listening on port 5000 and worker 10804

The output will vary depending on how many CPUs your system has.

Congratulations! You now have an HTTP server running on multiple CPUs!

Conclusion

The cluster module gives Node.js the much-needed ability to use the entire power a CPU provides by allowing us to easily create child processes. And it also does a ton of work in the background to communicate between the master and worker processes.

After working through this article, you should now know how to use that module to run an Express HTTP server on multiple CPU cores. With this knowledge, you will be able to better manage and scale your applications.

Thanks for reading and happy coding!


Tag cloud