A fully functional load balancer built from scratch in Java with 6 routing algorithms, health checking, chaos simulation, and concurrent request handling — no frameworks, no dependencies.
Load balancers are critical infrastructure at every large-scale company. This project implements the core algorithms used by real production load balancers (HAProxy, NGINX, AWS ALB) to demonstrate understanding of distributed systems, concurrency, and algorithm trade-offs.
╔══════════════════════════════════════════════════════════════╗
║ LOAD BALANCER FROM SCRATCH — Java 17 ║
║ 6 Algorithms · Health Checks · Concurrent Traffic ║
╚══════════════════════════════════════════════════════════════╝
━━━ Simulating: Weighted Round Robin ━━━
[CHAOS] Killing server svr-3 mid-simulation
[CHAOS] Recovering server svr-3
╔══════════════════════════════════════════════════════════════╗
║ LOAD BALANCER METRICS ║
╠══════════════════════════════════════════════════════════════╣
║ Total Requests: 500 ║
║ Failed Requests: 0 ║
║ Avg Latency: 43.50 ║
║ Throughput: 1351.35 req/s ║
╠══════════════════════════════════════════════════════════════╣
║ SERVER DISTRIBUTION ║
╠══════════════════════════════════════════════════════════════╣
║ ✓ svr-1 ██████████████████████████████ 197 reqs avg 31.4ms ║
║ ✓ svr-2 ███████████████████░░░░░░░░░░░ 129 reqs avg 51.4ms ║
║ ✓ svr-3 ██████░░░░░░░░░░░░░░░░░░░░░░░░ 45 reqs avg 78.2ms ║
║ ✓ svr-4 ███████████████████░░░░░░░░░░░ 129 reqs avg 42.0ms ║
╚══════════════════════════════════════════════════════════════╝
| Algorithm | Selection | Complexity | Best For |
|---|---|---|---|
| Round Robin | Sequential rotation | O(1) | Equal-capacity servers |
| Weighted Round Robin | GCD-based smooth scheduling | O(1) amortized | Heterogeneous server capacities |
| Least Connections | Min active connections | O(n) | Variable request durations |
| Least Response Time | Min average latency | O(n) | Performance-sensitive routing |
| IP Hash | FNV-1a deterministic mapping | O(1) | Session affinity without server-side state |
| Consistent Hashing | MD5 hash ring with 150 vnodes | O(log n) | Minimal remapping on topology changes |
- Round Robin is the simplest and fastest but ignores server capacity differences.
- Weighted Round Robin respects capacity but requires manual weight configuration.
- Least Connections adapts to real load but requires O(n) scan per request.
- Consistent Hashing minimizes disruption when servers join/leave — adding or removing a server only remaps ~1/n of keys. Uses a
TreeMap(red-black tree) for O(log n) ceiling lookups on the hash ring.
src/main/java/loadbalancer/
├── LoadBalancer.java # Core router: filters healthy servers, delegates to algorithm
├── Main.java # CLI entry point with chaos simulation
├── algorithm/
│ ├── BalancingAlgorithm.java # Strategy interface (pluggable)
│ ├── RoundRobin.java # AtomicInteger-based rotation
│ ├── WeightedRoundRobin.java # GCD-based smooth weight distribution
│ ├── LeastConnections.java # Min active connection scan
│ ├── LeastResponseTime.java # Min average latency scan
│ ├── IPHash.java # FNV-1a hash for session affinity
│ └── ConsistentHashing.java # MD5 hash ring with virtual nodes
├── server/
│ └── BackendServer.java # Thread-safe server with atomic counters
├── health/
│ └── HealthChecker.java # Scheduled health probes with failure threshold
└── metrics/
└── MetricsCollector.java # Atomic throughput/latency/distribution tracking
src/test/java/loadbalancer/
└── LoadBalancerTest.java # 10 unit tests covering all algorithms
Design patterns used:
- Strategy Pattern — algorithms are interchangeable via
BalancingAlgorithminterface - Observer — health checker asynchronously updates server state
- Thread-safe counters —
AtomicInteger/AtomicLongfor lock-free concurrent access
- 6 load balancing algorithms with pluggable strategy pattern
- Health checking with configurable interval and failure threshold
- Chaos simulation — servers go down and recover mid-test
- Concurrent traffic — 8-thread pool sends 500 requests per algorithm
- Metrics dashboard — throughput, latency, per-server distribution bars
- Thread-safe — atomic operations, no locks, safe under concurrent load
- 10 unit tests covering all algorithms, concurrency, and edge cases
- Zero dependencies — pure Java 17 standard library
# Run all 6 algorithms
./build.sh
# Run a specific algorithm
./build.sh round-robin
./build.sh weighted-round-robin
./build.sh least-connections
./build.sh least-response-time
./build.sh ip-hash
./build.sh consistent-hashing
# Run tests
./test.shRequirements: Java 17+
- Consistent hashing uses 150 virtual nodes per server for uniform distribution, with MD5 hashing and a
TreeMapfor O(log n) ring lookups - FNV-1a hash in IP Hash provides fast, well-distributed hashing with minimal collision rates
- Weighted round-robin uses GCD-based scheduling to avoid request bursts on high-weight servers
- Health checker runs on a daemon thread with
ScheduledExecutorService, configurable probe interval and consecutive-failure threshold before marking unhealthy - All counters use
java.util.concurrent.atomicclasses for lock-free thread safety
MIT
Mo Shirmohammadi — github.com/mohosy