HTTP Load Balancing

LinuxBeginner
Practice Now

Introduction

In this lab, you will learn the fundamentals of load balancing using HAProxy.

Imagine a bank with only one teller. The line gets very long, and customers get angry. To fix this, the bank opens multiple teller windows. However, you now need a manager at the door to direct each customer to the next available window.

In this scenario:

  • The Bank Manager is the Load Balancer (HAProxy).
  • The Tellers are the Backend Servers (simulated web servers).
  • The Customers are the Web Traffic.

You will build this setup on Linux. You will create two simulated web servers and configure HAProxy to split the traffic between them using round robin, one of the simplest balancing algorithms.

Round robin is useful as a starting mental model because it shows the basic purpose of a load balancer: distribute successive requests across multiple healthy backends instead of sending everything to one machine.

By the end of this lab, you will be able to:

  1. Run simple Python web servers.
  2. Configure HAProxy to accept traffic (Frontend) and send it to servers (Backend).
  3. See load balancing in action.

Prepare Terminals

To test a load balancer, we first need something to balance! We need to run two separate web servers at the same time. Since a running server occupies the terminal (it keeps running until you stop it), we cannot type new commands in the same window.

Therefore, we need to open extra terminal tabs. Think of this like opening multiple tabs in your web browser so you can look at different websites at once.

Operationally, this step helps separate roles in the system. The Python servers simulate your application tier, while the main terminal remains your control plane for the load balancer itself.

You currently have one terminal open (Terminal). Please open two more:

  1. Find the + (Plus) icon in the terminal interface.
  2. Click it twice to open Terminal 1 and Terminal 2.

We will use them like this:

  • Terminal: Our Control Center (for configuring HAProxy).
  • Terminal 1: Will run Server 1.
  • Terminal 2: Will run Server 2.

Start Server 1

Now we will start our first "Teller" (Server 1). Instead of installing heavy web server software, we will use a handy tool built into Python that turns any folder into a website.

Please switch to Terminal 1.

First, go to the folder we prepared for Server 1.

cd ~/project/server1

Now, start the server. We will tell it to listen on port 8001. Think of a port like an apartment number. The computer is the building, and port 8001 is the specific door where Server 1 lives.

python3 -m http.server 8001

You will see a message saying Serving HTTP on 0.0.0.0 port 8001. This means the server is running and waiting for visitors. This terminal is now "busy", so don't type anything else here.

Start Server 2

Let's start the second "Teller" (Server 2) so we have someone to share the work.

Please switch to Terminal 2.

Go to the folder for Server 2.

cd ~/project/server2

Start this server on a different port, 8002. We cannot use 8001 because Server 1 is already using it (two families can't live in the same apartment 8001).

python3 -m http.server 8002

Now you have two independent web servers running. One says "Response from Server 1" (on port 8001) and the other says "Response from Server 2" (on port 8002).

Configure Frontend

Now that our servers are ready, let's configure the "Bank Manager" (HAProxy) to direct traffic to them.

This is where the frontend and backend split begins. A frontend describes how clients arrive at HAProxy, while a backend describes the server pool that will actually handle the work.

Switch back to Terminal.

We will start fresh by backing up the old configuration and creating a new one.

sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
sudo nano /etc/haproxy/haproxy.cfg

Copy and paste the following text into the editor. This defines the Frontend. The Frontend is the public face of the load balancer—it's where the customers (users) arrive.

global
    log /dev/log    local0
    log /dev/log    local1 notice
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000

frontend http_front
    bind *:80
    default_backend http_back

Key parts to understand:

  • bind *:80: This tells HAProxy to listen on Port 80. Port 80 is the standard door for web traffic (HTTP). When you type a website name without a port, your browser goes to port 80.
  • default_backend http_back: This tells HAProxy, "When people arrive here, send them to the group called http_back."

That naming matters because HAProxy configuration is essentially a traffic map. Frontends receive connections, and backends represent the possible destinations for those connections.

Save the file (Ctrl+O, Enter) but you can keep it open if you want, or better yet, save and exit (Ctrl+X) to verify your progress step-by-step.

Configure Backend

Now we need to define that group of workers, the Backend.

Open the configuration file again if you closed it:

sudo nano /etc/haproxy/haproxy.cfg

Append the following lines to the end of the file:

backend http_back
    server server1 127.0.0.1:8001 check
    server server2 127.0.0.1:8002 check

What did we just do?

  • backend http_back: We created the group named http_back.
  • server server1 ...: We introduced our first worker (Server 1) at address 127.0.0.1:8001 (localhost port 8001).
  • server server2 ...: We introduced our second worker (Server 2) at 127.0.0.1:8002.
  • check: This is crucial. It tells the Manager to periodically check if the worker is actually there (Healthy). If a server crashes, HAProxy will stop sending people to it.

Save the file (Ctrl+O, Enter) and exit (Ctrl+X).

Verify Balancing

How should the Manager decide who gets the next customer? The most common way is Round Robin. It's simply "taking turns".

  • Customer 1 -> Server 1
  • Customer 2 -> Server 2
  • Customer 3 -> Server 1
  • ...and so on.

Let's make this explicit in our configuration. Open the configuration file one last time:

sudo nano /etc/haproxy/haproxy.cfg

Find the backend http_back section you just added, and insert the balance directive so it looks like this:

backend http_back
    balance roundrobin
    server server1 127.0.0.1:8001 check
    server server2 127.0.0.1:8002 check

Note: Indentation (spaces at the start of the line) matters for readability, although HAProxy is forgiving. Try to keep it tidy.

Save the file (Ctrl+O, Enter) and exit (Ctrl+X).

Reload HAProxy and Test

The configuration is ready, but HAProxy doesn't know about it yet. We need to reload the service to apply the changes.

sudo service haproxy restart

Now for the moment of truth! We will use a command called curl. Think of curl as a web browser without a graphical interface. It fetches a webpage and shows the text code on your screen.

We will connect to localhost (our machine) on the default port 80 (where HAProxy is listening).

Run this command multiple times:

curl localhost

You should see "Response from Server 1". Run it again.

curl localhost

Now you should see "Response from Server 2".

If you want to see it happen fast, you can run this loop command, which hits the server 4 times in a row:

for i in {1..4}; do
  curl localhost
  echo
done

You should see the output alternate perfectly: 1, 2, 1, 2.

This proves that your Load Balancer is working! It is receiving your requests on port 80 and fairly sharing the work between port 8001 and port 8002.

Summary

In this lab, you successfully built a Load Balanced Web Cluster!

Here is what you achieved:

  1. Simulated Backends: You used Python to create two working web servers on different ports (8001, 8002).
  2. Configured Frontend: You told HAProxy to listen on the standard web port (80).
  3. Configured Backend: You registered your two servers as the workforce.
  4. Round Robin: You set up a fair "taking turns" policy for distributing traffic.

This is the exact same architecture used by massive websites to handle millions of users, just on a smaller scale.