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)
}