Follow by Email

NodeJS Scaling - Forking processes


As Node.js is single threaded, we've run into the need to scale our applications much sooner that we would if we were using another programming language.

This is actually a benefit of Node because we get to talk about scaling much earlier in the application lifecycle because Node applications are made to scale.
Node.js is designed to clone your application and then run it using multiple instances simultaneously. This process is called forking.

Let's take a look at how we can fork our advice server. In your app.js file, So here we have an HTTP server that's serving advice. On line four, those are the advice options. So this server's going to randomly give you one of these options. Below code explains forking :
In App.js

const http = require('http')
const port = parseInt(process.argv[2] || '3000')
 
const options = [
    "data",
    "data2"
 
]
 
const server = http.createServer((req, res) => {
    const randomIndex = Math.floor(Math.random() * options.length)
    const payload = JSON.stringify({
        port,
        processID: process.pid,
        advice: options[randomIndex]
    })
 
    res.writeHead(200, { 'Content-Type': 'application/json'})
    res.end(payload)
})
 
server.listen(port)
console.log(`advice service running on port ${port}`)

On line 12, that's where we create the server, and we are randomly selecting the option because of line 13 where we set the random index using Math.random. Then we'll create a payload so that we can return the port, the ID of the current process, and some random advice. And then we will respond with that payload on line 21. 

So another thing to notice is that on line 2, we are setting the port from the process.argv array. These are the arguments that are passed to this script when it starts. We can run our server by going over to the terminal and typing node app and then the port we'd like to use, 3001. So I just started an advice service running on port 3001. I can come over here to the browser. All right, and then when I hit the server using the browser, localhost:3001, we get to see the port, the processID, and some random advice. Every time I hit refresh, we can see that the advice changes. Now this is great, but because we only have one instance of one process running, we're only gonna be able to handle so much traffic. So the solution is to fork this process. 

In the index.js file we want to do is get the fork function from the child_process module. Here we have fork the app into three instances. Now we need to send the port to the app to start it, so the fork function is very similar to the spawn function and the execute function in that it will take an array of arguments. In index.js

const { fork } = require('child_process')
const processes = [
  fork('./app', ['3001']),
  fork('./app', ['3002']),
  fork('./app', ['3003'])
]
console.log(`forked ${processes.length} processes`)


So this first one will run on 3001. The second app will run on 3002. And this third app will run on 3003. We have forked processes.length. Once you run the index file, we will actually fork our application. it will clone it into three processes, each running on its own port.  And you can see that it says forked three processes. If I come over to the browser, we'll notice on 3001, we have an advice server running. On 3002, we also have an advice server running. And on 3003, we have an advice server running. 

So we've created three node instances. Each have their own memory, and they each have their own processID. So we can see that this is 7957, this is 7956, and this is 7955. They're all running the same code. This is a small example of how we can use the fork method available to us within the child_process module. Here, we took our application, our app.js file, and forked it into three separate instances that use the same code.