How to load Balancing NodeJs apps using Nginx?

In this article we’re going to learn how to load Balancing NodeJs applications using Nginx.

At first, if you are don’t familiar with Nginx, please read the article in the below link to understand what is Nginx .

THE ISSUE

If your application hasn’t many requests you don’t have to use load balancing, but when your application becomes famous and popular :) it is going to be able handle many traffic hits, so single NodeJs setup is not flexible for doing that.

In this picture you can see how does a single NodeJs setup with Nginx reverse proxy works.

single Nodejs setup with reverse proxy

SOLUTION

In high traffic apps we need to distribute requests between multiple http servers like this diagram.👇

In our example we’ve 4 instances of one Node.js app that listening on different ports, also you can run your instances in other servers with different IPs.

This is a simple Nodejs application.

const http = require('http');
const hostname = '127.0.0.1';
const port =  process.argv[2] || 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});

We need a NodeJs process manager to run our NodeJs apps in the background, so we use pm2 process manager .

Run application in 4 different ports like this :

pm2 start server.js -- 444
pm2 start server.js -- 445
pm2 start server.js -- 446
pm2 start server.js -- 447

Well , now we’ve 4 instances of our simple NodeJs application.

Create a new file in /etc/nginx/conf.d/ called your-domain.com.conf and put this on it:

If you have it , please open and edit it.

upstream my_http_servers {
server 127.0.0.1:444; # httpServer1 listens to port 444
server 127.0.0.1:445; # httpServer2 listens to port 445
server 127.0.0.1:446; # httpServer3 listens to port 446
server 127.0.0.1:447; # httpServer4 listens to port 447
}
server {
listen 80;
server_name your-domain.com www.your-domain.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://
my_http_servers;
}
}

Upstream in nginx defines a group of servers. Servers can listen on different ports. In addition, servers listening on TCP and UNIX-domain sockets can be mixed.

Choosing a Load Balancing Method

Load balancing in Nginx has different methods :

1 — Round-robin

In this method requests are distributed evenly across the servers with server weights taken into consideration. This method is used by default (there is no directive for enabling it).

In our Example :

upstream my_http_servers {
server 127.0.0.1:444; # httpServer1 listens to port 444
server 127.0.0.1:445; # httpServer2 listens to port 445
server 127.0.0.1:446; # httpServer3 listens to port 446
server 127.0.0.1:447; # httpServer4 listens to port 447
}

2 — least_conn

A request is sent to the server with the least number of active connections with server weights taken into consideration:

In our Example :

upstream my_http_servers {
least_conn;
server 127.0.0.1:444; # httpServer1 listens to port 444
server 127.0.0.1:445; # httpServer2 listens to port 445
server 127.0.0.1:446; # httpServer3 listens to port 446
server 127.0.0.1:447; # httpServer4 listens to port 447
}

3 — ip_hash

The server to which a request is sent is determined from the client IP address. In this case, either the first three octets of IPv4 address or the whole IPv6 address are used to calculate the hash value. The method guarantees that requests from the same address get to the same server unless it is not available.

If you use socket.io you need to use the ip_hash directive . Very important else you’ll get these “Invalid Request” errors from your app.

You can get more information about load balancing methods at nginx official web site.

Ok, let’s choose least_conn;

This is our final config file.

upstream my_http_servers {
least_conn;
server 127.0.0.1:444; # httpServer1 listens to port 444
server 127.0.0.1:445; # httpServer2 listens to port 445
server 127.0.0.1:446; # httpServer3 listens to port 446
server 127.0.0.1:447; # httpServer4 listens to port 447
}
server {
listen 80;
server_name your-domain.com www.your-domain.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://
my_http_servers;
}
}

And finally restart nginx service .

sudo service nginx restart

Conclusion

In this article we’re created a simple NodeJs application and distribute requests between multiple instances of it .

In other article I’m going to write more about NodeJs applications in production.

Finally, If you have an idea or experience about load balancing NodeJs applications please tell me in comments and I’ll add them to article.