Load-balancing APIs using Nginx with Example

May 26, 2019
by Rahil Shaikh

Load balancing involves distributing API load to multiple backend servers efficiently. This task is done by a load balancer.

Load balancing allows your APIs to perform optimally even during peak loads, improves fault-tolerance and improves performance. Nginx started out primarily as a high-performance web server but in addition, to this, it is very well suited to be used as a reverse proxy and a load balancer for HTTP.

Most of the articles out there only show how to configure Nginx as a load balancer, which is fine. But in this article I will follow a different approach, we will see Nginx in action with an example.

We will set up two HTTP API servers run them on different ports and load balance them using Nginx.

Set up

We can very well perform this experiment on a local machine, but for this tutorial, I’ll be hosting everything on a DigitalOcean Droplet. You will get 100$ free credit on DigitalOcean if you signup via this link, I’ll get 25$.

First, we need to install Nginx.

sudo apt update

sudo apt install nginx

Check if Nginx is running.

systemctl status nginx

If it’s running then you will be able to see Nginx home page on your IP address.

http://your_server_ip

Spin up API servers

Let’s spin up a couple of APIs on two different servers which will be load-balanced.
I’ll be creating APIs in Node.js. Coz that is the fastest way to spin up an API server. For this, we will need to have Node.js installed.

curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install nodejs

Create a new directory server1. This will be our API 1.

server1 – app.js
const express = require('express');
const app = express();

const servername = 'Ciphertrick Server 1'

app.get('/servername', (req, res)=>{
   res.send(servername);
});

app.listen(3000, ()=>{
        console.log('Listening on ', 3000);
});

It simply has an API that returns the server name.

Similarly, create another directory server2 and add the same API, but simply change the server name returned and the listening port.

Server2 – app.js
const express = require('express');
const app = express();

const servername = 'Ciphertrick Server 2'

app.get('/servername', (req, res)=>{
   res.send(servername);
});

app.listen(3001, ()=>{
        console.log('Listening on ', 3001);
});

One very important thing to understand here is that we are creating two API server only for demo purposes, in the real world, you will have the same code base running on completely different VM’s with mostly identical configurations, and a separate Nginx server that sits on top of them distributing the load.

Now we need to run these two API servers in the background. For this, I’ll use the pm2 process manager.

npm i pm2 -g

cd ~/server1
pm2 start app.js --name=server1

cd ~/server2
pm2 start app.js --name=server2

Let’s see if our APIs are running…

root[email protected]:~/server2# curl localhost:3000/servername
Ciphertrick Server 1

[email protected]:~/server2# curl localhost:3001/servername
Ciphertrick Server 2

Okay so now we have everything in place except the load balancer. Let’s move in to do just that.

Setting up Nginx as Load Balancer with round-robin startegy

There are multiple strategies that can be used for load-balancing, we will start with the simplest, which is Round-Robin.

Open up the Nginx configuration file in the editor of your choice.

cd /etc/nginx/sites-available/

sudo nano default

Add upstream which will include the list of servers to load-balance.

upstream backend  {
        server 127.0.0.1:3000;
        server 127.0.0.1:3001;
}

Then under the server block comment root and add proxy_pass…

#       root /var/www/html;

        # Add index.php to the list if you are using PHP
#       index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                proxy_pass http://backend;
                #try_files $uri $uri/ =404;
        }

Test out if the Nginx configuration is valid.

nginx -t

Reload Nginx.

sudo systemctl reload nginx

Now, open up the API URL on your browser…

http://your-server-ip/servername

This should display Ciphertrick Server 1 on the first hit and if you reload the same page you should see Ciphertrick Server 2. This is Nginx load-balancing your APIs in a Round-Robin fashion.

Another way to test it out is by simply doing a curl from within the server.

//first request
[email protected]:/etc/nginx/sites-available# curl localhost/servername
Ciphertrick Server 1

//second request
[email protected]:/etc/nginx/sites-available# curl localhost/servername
Ciphertrick Server 2

Weighted Load Balancing in Nginx

Round-robin is the most basic of load-balancing strategies that Nginx provides and that is the strategy used by default unless any other is specified.
In weighted load-balancing, the load is distributed based on weights provided. Have a look below.

upstream backend  {
        server 127.0.0.1:3000 weight=1;
        server 127.0.0.1:3001 weight=2;
}

In the above configuration, Nginx will send twice as much traffic to Server 2 as compared to Server 1. The default weight is 1.

Sticky Load Balancing using Nginx

The above strategies work when we can randomly redirect requests. But in cases where we need to deal with user-session, we need to direct a particular user to the same server on every subsequent request. For this Nginx provides ip_hash strategy. In this strategy, Nginx redirects request based on the client’s IP address. Hence requests originating from same IPs are always redirected to the same server.

upstream backend  {
        ip_hash;
        server 127.0.0.1:3000;
        server 127.0.0.1:3001;
}

Conclusion

Load balancing helps to improve the performance and resilience of your API servers, it mitigates risks of failures and betters risk governance. Nginx has come out to be the top web-server in the past few years but not only that it can very well perform other important tasks like reverse-proxy and load-balancing. In this article, we have learned how to setup Nginx as a load balancer with an example.

Keep Learning…

About

Engineer. Blogger. Thinker. Loves programming and working with emerging tech. We can also talk on Football, Gaming, World Politics, Monetary Systems.

Get notified on our new articles

Subscribe to get the latest on Node.js, Angular, Blockchain and more. We never spam!
First Name:
Email:

1 comment

Leave a Comment