This repository contains a Go-based Load Balancer implementation designed to distribute incoming HTTP requests across multiple backend servers (nodes). The Load Balancer uses a combination of Round Robin and weighted selection with a heap to ensure efficient load distribution and reliability through health checks.
- Load Balancer - README
- Node Selection and Heap Example
- Node State After Health Check
- Explanation
- License
- Round Robin and Weighted Selection: Balances the load across available nodes using a hybrid approach.
- Health Checks: Regularly verifies the status of nodes and adjusts their weights accordingly.
- Dynamic Node Management: Allows adding or removing nodes on the fly.
- Retry Mechanism: Retries requests a specified number of times before marking a node as inactive.
- Node Pool: The Load Balancer maintains a pool of backend servers (nodes), each with a URL, an active status, and a weight that influences the selection process.
- Request Routing: Incoming requests are routed to the next available node based on a weighted selection algorithm. The weight reflects the node's reliability and capacity.
- Health Checks: Nodes are periodically checked for availability, and their weights and statuses are updated based on the results.
- Retries and Failover: If a request to a node fails, the Load Balancer retries the request with the same or another node up to three times before marking the node as inactive.
- Clone the repository:
> git clone https://github.com/sanjay-sol/Load_Balancer.git > cd Load_Balancer
- Install dependencies:
> go mod tidy
-
Start the Load Balancer:
> go run cmd/main.go -nodeList=http://backend1.com,http://backend2.com -port=3030
Replace
http://backend1.com
andhttp://backend2.com
with your backend server URLs. Theport
flag specifies the port for the Load Balancer.- Example ( Start the simple test servers -- express/any on ports 8081,8082,8083)
> go run cmd/main.go -nodeList=http://localhost:8081,http://localhost:8082,http://localhost:8083 -port=3030
-
Accessing the Load Balancer: Once started, the Load Balancer listens for incoming HTTP requests on the specified port and routes them to the backend servers.
> curl http://localhost:3030
see the Requests sent to different servers automatically each time
The Round Robin method is a straightforward and popular load balancing technique. It distributes client requests in a circular order, ensuring that each node receives an equal share of the load. Here's how it works:
-
Initial State:
- Nodes: A, B, C
- Current Node: A
-
Request Sequence:
- 1st Request: Node A
- 2nd Request: Node B
- 3rd Request: Node C
- 4th Request: Node A (cycle repeats)
- Nodes:
A
,B
,C
- Incoming Requests: 5
Request | Node |
---|---|
1 | A |
2 | B |
3 | C |
4 | A |
5 | B |
In this example, Node A receives the 1st and 4th requests, Node B receives the 2nd and 5th, and Node C receives the 3rd request.
Heapify is a process that arranges nodes into a binary heap based on their weights, ensuring that nodes with higher weights are given priority. The Load Balancer uses a max-heap structure where the root node has the highest weight, making it the preferred choice for the next request.
-
Initial Heap:
- Nodes:
[Node 1 (weight: 1.0), Node 2 (weight: 0.5), Node 3 (weight: 0.8)]
- Nodes:
-
Heapify Process:
- Compare the weights of the nodes.
- Swap nodes to ensure the largest weight is at the root.
-
Resulting Heap:
- Nodes:
[Node 1 (weight: 1.0), Node 3 (weight: 0.8), Node 2 (weight: 0.5)]
- Nodes:
- Nodes:
A (weight: 1.0)
,B (weight: 0.5)
,C (weight: 0.8)
Step | Action | Heap Order |
---|---|---|
1 | Initialize heap | A (1.0), B (0.5), C (0.8) |
2 | Compare A and C | A (1.0), B (0.5), C (0.8) |
3 | C > B, swap B and C | A (1.0), C (0.8), B (0.5) |
4 | A is root (no changes needed) | A (1.0), C (0.8), B (0.5) |
In this example, Node A remains at the top due to its highest weight, followed by Node C and then Node B.
The Load Balancer performs periodic health checks on each node to ensure they are active and capable of handling requests. Nodes that fail the health check are marked as inactive and their weights are adjusted to minimize or eliminate their use in routing decisions.
-
Initial State:
- Nodes:
[Node 1 (weight: 1.0, active), Node 2 (weight: 1.0, active)]
- Nodes:
-
Health Check:
- Node 1: Successful
- Node 2: Unsuccessful
-
Updated State:
- Nodes:
[Node 1 (weight: 1.0, active), Node 2 (weight: 0.33, inactive)]
- Nodes:
In this scenario, Node 2's weight is reduced, making it less likely to be chosen for future requests.
graph TD
A[Client] -->|HTTP Request| B[Load Balancer]
B -->|Selects Node| C1[Backend Node 1]
B -->|Selects Node| C2[Backend Node 2]
C1 -->|HTTP Response| A
C2 -->|HTTP Response| A
D[Health Check] --> B
B -.->|Check Status| C1
B -.->|Check Status| C2
Node | Initial Weight | Status |
---|---|---|
Node A | 1.0 | Active |
Node B | 1.0 | Active |
Node C | 0.8 | Active |
Node A: Weight 1.0
Node B: Weight 1.0
Node C: Weight 0.8
After performing a health check, the status and weights of the nodes are updated as follows:
Node | Updated Weight | Status |
---|---|---|
Node A | 1.0 | Active |
Node B | 0.33 | Inactive |
Node C | 0.8 | Active |
The nodes are arranged in a heap based on their updated weights. The heap helps in efficiently selecting the next node for handling incoming requests, giving priority to nodes with higher weights.
Node A: Weight 1.0
Node C: Weight 0.8
Node B: Weight 0.33
- Node A: With a weight of 1.0 and active status, Node A remains at the top of the heap, indicating its readiness to handle requests.
- Node C: Node C, with a weight of 0.8, is the next preferred node due to its relatively high weight and active status.
- Node B: Node B has the lowest weight of 0.33 and is currently inactive. It is placed at the bottom of the heap, reflecting its reduced priority for handling requests.