Skip to main content

Implementing load balancing with HAProxy in Node.js apps

What is a load balancer?

Load balancers distribute incoming client requests to computing resources such as application servers and databases. In each case, the load balancer returns the response from the computing resource to the appropriate client.

Why use a load balancer?

  • Preventing requests from going to unhealthy servers
  • Preventing overloading resources
  • Helping to eliminate a single point of failure

This introduction is enough to get started.

For this tutorial, we are going to use HAProxy which is a free, very fast, and reliable solution offering high availabilityload balancing, and proxying for TCP and HTTP-based applications.

We are not going to create a Node.js application here. For this tutorial let’s say you have a node.js application up and running on localhost:3000

When clients hits the server on localhost:3000 the server returns the appropriate response. Now let's say if we start sending a lot of requests to this single server, the server will get overloaded and the response time will decrease. Also if this server crashes client won’t be able to get the response. That means currently our app is not scalable and is not highly available.

There are two ways to address the scalability issue, we can allocate more resources such as ram to handle more user in less response time. That's called Vertical Scaling. The second approach would be to create multiple instances of your server and distribute the requests between them. This is known as Horizontal Scaling.

Now you may be wondering how effectively distribute the requests between those servers. This is where you can use HAProxy.

Image for post
HAProxy

Now let's set up the HAProxy.

  1. Install HAProxy in ubuntu
sudo apt-get update
sudo apt-get install haproxy

2. Configure the HAProxy

sudo nano /etc/haproxy/haproxy.cfg

3. Put this configuration in the haproxy.cfg

defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend localnodes
bind *:80
mode http
default_backend nodes
backend nodes
mode http
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server app01 127.0.0.1:3000 check
server app02 127.0.0.1:3001 check
server app03 127.0.0.1:3002 check
listen stats
bind :9000
stats enable
stats uri /
stats hide-version
stats auth someuser:password

4. Restart the HAProxy

sudo service haproxy restart

Now go to localhost:9000 and you should be able to view the HAProxy statistics dashboard after providing username and password.

Image for post
HAProxy statistics dashboard

As you can see app01, app02 and app03 are showing as down.

Now go ahead and start your node server on localhost:3000, and two more servers on localhost:3001 and localhost:3002.

As soon as you start the server you can see the status on the HAProxy statistics dashboard.

Image for post

Now let’s send some requests to our load balancer, we don’t need to call localhost:3000 or localhost:3001 we can just hit on localhost since HAProxy running on port 80.

The load balancer should be able to get the requests and forward it to node.js servers using the Round Robin algorithm.

Create a script and make 10000 requests to your server. And you will be able to see that the requests have been balanced between these three servers.

This ensures that you will be able to handle the requests even if one of your servers goes down.

Image for post

As you can see above the 10,000 requests have been distributed effectively between the three servers.

You can choose your own algorithm for load balancing, lets try the Weighted Round Robin algorithm.

Update your haproxy.cfg with:

backend nodes
mode http
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server app01 127.0.0.1:4321 weight 5 check
server app02 127.0.0.1:4322 weight 3 check
server app03 127.0.0.1:4323 weight 2 check

Here we have given the weight to each server. The app01 server has a weight of 5, app02 has 3 and app03 has 2.

Now let's see this in action, fire 10,000 requests, and see the statistics.

Image for post

Now as you can see the requests have been distributed as per the weight to three servers.

app01: 5000

app02: 3000

app03: 2000

You can use different load balancing algorithms as per your need.

If you are interested in System Design, also read how to setup Nginx as a reverse proxy here.

https://blog.shashi.dev/2021/01/setting-up-nginx-as-reverse-proxy-for.html

Thanks for reading. If you have some feedback, please provide your response or reach out to me on Twitter or Github.

Happy Coding!!!

Comments

Popular posts from this blog

Track stock market information right in your Terminal.

     Introduction: As a developer, I love working with the terminal. The plain, simple, and in my opinion the best way to interact with the computer (also it makes you look geeky). I spent most of my time in the terminal. By now you must have guessed I am a huge fan of the terminal and terminal-based applications. Recently I developed an interest in stock markets and started tracking the stock markets. Since I love working with the terminal I decided to build a terminal oriented application that can help me to track the stock market. Inspir e d by  wttr.in  I build  terminal-stocks  which can provide the stock's current prices, historical prices, and global market summary. How to use terminal-stocks terminal-stocks  is available and can be used without installation. Get the current price of the stock. curl terminal-stocks.herokuapp.com/ITC.NS Current price of stocks You need to provide the ticker of the stock and terminal-stocks will give you the price information of the stock.  t

Setting up Nginx as a reverse proxy for Node.js App

Okay.. but what is a reverse proxy? A reverse proxy is a web server that centralizes internal services and provides unified interfaces to the public. Requests from clients are forwarded to a server that can fulfill it before the reverse proxy returns the server’s response to the client. Nginx is a popular choice to use as a reverse proxy for your node.js application. Got it. Now let’s set up Nginx Let’s say your nodejs server is running locally on localhost:3000. We will set up Nginx to get the request and forward the request to our nodejs server. Ins t alling Nginx on ubuntu sudo apt-get update sudo apt-get install nginx Configure Nginx Disable the default, virtual host unlink /etc/nginx/sites-enabled/default 2. Create a configuration file cd /etc/nginx/sites-available sudo nano reverse-proxy.conf 3. Put the following content in the file server { listen 80; listen [::]:80; access_log /var/log/nginx/reverse-access.log; error_log /var/log/nginx/reverse-e

RESTful CRUD API with Deno, Oak and MongoDB

In this post, we are going to build a RESTful CRUD API with Deno, Oak and MongoDB as database. In the previous article, we discussed how to install deno in your local machine and start using Deno. If you haven’t read that article, please read the article below and install the deno first. Getting started with Deno, Your first app Hello Deno. Let's install Deno. Deno ships as a single executable with no dependencies. You can install it using the installers… blog.shashi.dev After installing the Deno, we will start building the restful crud api’s. We will use o ak  microframework. Some of the other deno microframeworks are: abc deno-drash deno-express oak pogo servest In this article we will be using oak, which is inspired by koa. Setting up the project: Create a new directory called  restful-api-deno mkdir restful-api-deno 2. After c r eating the directory just  cd  into the directory cd restful-api-deno 3. Create a new file  server.ts  and paste the following code init. import { Ap