This repository contains an implementation of a customizable load balancer that distributes client requests across multiple server replicas using consistent hashing. The system is designed to maintain N server instances even in case of failures, automatically spawning new replicas when needed.
- System Architecture
- Implementation Details
- Setup Instructions
- API Documentation
- Performance Analysis
- Design Choices
- Testing
- Future Improvements
The system consists of:
- Load Balancer: Routes client requests to appropriate servers using consistent hashing
- Server Replicas: Multiple instances of a simple web server that handle requests
- Docker Network: Internal network connecting all components
We implemented consistent hashing with the following parameters:
- Number of slots (M) = 512
- Virtual servers per physical server (K) = 9 (log₂512)
- Hash functions:
- Request mapping: H(i) = i + 2i + 1
- Virtual server mapping: Φ(i,j) = i + j + 2j + 25
Each physical server is represented by K virtual servers in the hash ring, ensuring better load distribution during failures.

The load balancer periodically checks server health via heartbeat endpoints. If a server fails:
- It's removed from the hash ring
- A new replica is spawned
- Virtual servers are recreated for the new instance
- Docker (version 20.10.23 or above)
- Docker Compose
- Ubuntu 20.04 LTS or above
-
Clone the repository:
git clone https://github.com/TamaraChelagat/load-balancer-distributed-systems.git cd load-balancer-distributed-systems -
Build and run the system:
make build make up
-
To stop the system:
make down
-
GET /rep
- Returns current server replicas
- Example response:
{ "message": { "N": 3, "replicas": ["Server1", "Server2", "Server3"] }, "status": "successful" }
-
POST /add
- Adds new server instances
- Example request:
{ "n": 2, "hostnames": ["S4", "S5"] }
-
DELETE /rm
- Removes server instances
- Example request:
{ "n": 1, "hostnames": ["S3"] }
-
GET /
- Routes requests to server replicas
- Example:
/homeroutes to servers' home endpoint
-
GET /home
- Returns server identifier
- Example response:
{ "message": "Hello from Server: 3", "status": "successful" }
-
GET /heartbeat
- Health check endpoint
- Returns empty response with 200 status code
- Observation: Requests were nearly evenly distributed across all servers
- Server 1: 3,342 requests (33.42%)
- Server 2: 3,317 requests (33.17%)
- Server 3: 3,341 requests (33.41%)
The consistent hashing algorithm with virtual servers effectively balanced the load.
| N | Average Load per Server |
|---|---|
| 2 | 5000 |
| 3 | 3333 |
| 4 | 2500 |
| 5 | 2000 |
| 6 | 1666 |
- Observation: As N increases, the average load per server decreases linearly
- The system scales well with additional servers
- When a server was manually stopped:
Using alternative hash functions showed:
- Similar load distribution patterns
- Slightly different distributions but still balanced
- Confirmed algorithm robustness to hash function variations

-
Language Selection: Python was chosen for rapid development and rich ecosystem for web services.
-
Virtual Server Count: K = log₂512 was selected based on statistical analysis showing optimal load distribution.
-
Failure Detection: Heartbeat checks every 3 seconds for timely failure detection.
-
Container Management: Privileged containers used to enable dynamic replica management.
-
Conflict Resolution: Linear probing implemented for hash slot conflicts.
The system was tested with:
- Unit tests for hash functions and consistent hashing
- Integration tests for API endpoints
- Stress tests with up to 10,000 concurrent requests
- Failure scenarios (manual server termination)
To run tests:
make test- Implement weighted consistent hashing for heterogeneous servers
- Add more sophisticated health checks
- Implement request queuing during failover
- Add logging and monitoring
- Support dynamic adjustment of virtual server count
MIT License


