Follow by Email

NodeJS Scaling - Using cluster module


In Node.js, a single application instance only uses one processor because Node.js is single threaded. Forking your application into multiple instances is required to take full advantage of your hardware. 
A cluster is a group of node instances that all work together. A cluster is made up of worker processes, the four instances of our app, in a main process, which is the instance that spawns and controls the workers. 




Steps for creating clusters:
Let's create a cluster to take advantage of every CPU that is available to us. In the below example in index.js
1)       So the first thing is check for the CPUs on this machine. So if I use the OS module, and then invoke the CPUs function, this will give me information about every processor that I have available on this machine. So, if we come over to our terminal and run the index, we can see that we have what looks to be about eight Intel processors running on this machine. 
2)      Adding the cluster module to our code. And the cluster module is also available inside of the node core.
3)      Get the number of CPUs that we have and I can get that just by turning on a length because it returns an array. So that gives us the number of CPUs that we have. 
4)      Now I can check our cluster module to find out if this is the master process if this is the master process then cluster.fork to clone this process. And in fact, if I do it three times, I will have created three processes. 
5)      Take a look at the process ID. So we'll look at the PID inside of this console log and we'll also look for the PID inside of this console log. Go to the terminal and run the server.  On 8003, we have this is the master process.8004, this is the worker process. 8005, worker, 8006, worker. So this cluster allowed us to clone several processes. 
6)      Create a for loop, where i equals zero and i is less than our number of CPUs, i ++ and we're make sure we call cluster.fork for each of the CPUs that we have available to us. So this should start about nine processes. Eight worker processes and the main process. So within the worker process, instead of just logging the process ID,  we serve it. 
7)      Import the HTTP and down here, we'll create a server and make sure that we're listening on port 3000. So, this server will get every request to go to this handler and we'll create a message and put the process ID here. 
8)      But, if we come over to the browser and hit localhost:3000, we can see that we're hitting the same worker process. Now, what you'll notice is is every time I hit the browser, I am hitting worker process 8016. That's because we're not getting enough traffic to really use the rest of the processes. So from within the terminal install an NPM that will allow us to run a node test. 
9)      So you can type sudo npm install loadtest -g because we want to install this package globally. Once the  loadtest installed, start node so that we have our main processes running and we have eight worker processes running here, hit command T to open up a new terminal tab. And from this new terminal tab, run a loadtest. loadtest the number 300 hits, the site, http://localhost:3000. To simulate some traffic and let's watch this traffic spread out. So what you'll notice is each of these workers are actually being hit. We can see the different process IDs. Remember, every time we make a web request, we are creating a server that's will to let us know what the worker process ID is and then we are logging. So in the terminal, that's what we're seeing, and you can notice that when we have 300 requests, we're actually spreading the load out across eight different processors and taking full advantage of our machine. 
   Below Example code for clusters :

    
const http = require('http')
const cluster = require('cluster')
const numCPUs = require('os').cpus().length
 
if (cluster.isMaster) {
  console.log('this is the master process: ', process.pid)
  for (let i=0; i<numCPUs; i++) {
    cluster.fork()
  }
} else {
  http.createServer((req, res) => {
    const message = `worker ${process.pid}...`
    console.log(message)
    res.end(message)
  }).listen(3000)
}