System DesignMastery
--Foundations — ভিত্তি তৈরি

Load Balancing

Duration৩০-৪৫ মিনিট
LevelIntermediate
FocusTraffic Management
001Core Concept

Load Balancer কী?

ধরুন একটা bank এ ১০টা counter আছে, কিন্তু সবাই একটা counter এ গিয়ে দাঁড়াচ্ছে। বাকি ৯টা counter খালি পড়ে আছে। এটা কি বোকামি না?

Load Balancer হলো সেই manager যে দরজায় দাঁড়িয়ে বলে — "আপনি counter 3 এ যান, আপনি counter 7 এ যান।" প্রতিটা counter সমান কাজ পায়, কেউ overwhelmed না।

সেরকমভাবে, যখন লক্ষ লক্ষ user আপনার app এ request পাঠায়, Load Balancer সেই request গুলো বিভিন্ন server এ distribute করে দেয়।

DEFINITION

Load Balancer হলো এমন একটি component যা incoming network traffic কে multiple servers এর মধ্যে distribute করে। এটা নিশ্চিত করে যে কোনো একটা server অতিরিক্ত load এ overwhelmed না হয়।

Load Balancer এর Benefits

  • High Availability: একটা server down হলেও app চলতে থাকে
  • Scalability: নতুন server যোগ করে traffic handle করা সহজ
  • Performance: Load সমান ভাগ হওয়ায় response time কমে
  • Zero-downtime deployment: একে একে server update করা যায়, app বন্ধ হয় না
002L4 vs L7

L4 vs L7 Load Balancing

LAYER 4 Transport Layer

শুধু IP address + Port দেখে routing করে। HTTP content দেখে না। অনেক fast কারণ packet inspect করে না। কিন্তু content-aware না — URL বা header দেখে decision নিতে পারে না।

LAYER 7 Application Layer

পুরো HTTP request পড়তে পারে — URL, headers, cookies, body। Smart routing করতে পারে। যেমন /api/* → API servers, /static/* → CDN।

FeatureLayer 4Layer 7
OSI LayerTransport (L4)Application (L7)
Speedঅনেক FastSlightly Slower
Content Awarenessনা — IP+Port onlyহ্যাঁ — URL, Header, Cookie
SSL Terminationনাহ্যাঁ
Path-based Routingনাহ্যাঁ
Best ForUltra-low latency, TCP/UDPHTTP apps, Microservices
ToolsAWS NLB, HAProxy (TCP mode)Nginx, AWS ALB, Traefik
003Algorithms

Load Balancing Algorithms

Round Robin

সব server কে sequentially request পাঠাও। Server 1 → Server 2 → Server 3 → Server 1 → ... Simple এবং equal distribution। সব server একই capacity হলে ভালো।

Weighted Round Robin

Server এর capacity অনুযায়ী weight assign করুন। Server A (weight=3) → Server B (weight=1)। বড় server বেশি traffic পাবেন। Mixed hardware এ ভালো।

Least Connections

যে server এর active connections সবচেয়ে কম, তাকে request পাঠাও। Long-lived connections (WebSocket, database) এর জন্য সবচেয়ে ভালো। Variable request duration handle করে।

IP Hash

Client এর IP address hash করে always same server এ পাঠাও। Session persistence এর জন্য দরকার। Same user সবসময় same server এ যাবেন।

Random

Randomly একটা server select করুন। Simple কিন্তু uneven distribution হতে পারে। Production এ rarely ব্যবহার হয়।

Algorithmকীভাবে কাজ করেBest ForProblem
Round RobinSequential rotationEqual capacity serversLoad consider করে না
Weighted RRCapacity-based weightMixed hardwareStatic weight, dynamic load না
Least ConnectionsLowest active connectionsLong-lived connectionsConnection count != actual load
IP HashIP → same serverSession persistenceUneven distribution possible
RandomRandom selectionSimple testingProduction এ unpredictable
004Health Check

Health Check ও Failover

Load Balancer periodically সব servers কে ping করে দেখে তারা alive আছে কিনা। কোনো server respond না করলেন সেটাকে automatically rotation থেকে বাদ দেয়। Server ঠিক হলে আবার যোগ করে নেয়। এটাই Automatic Failover

Health Check এর ধরন

  • TCP Check: শুধু port open আছে কিনা check করে। দ্রুত কিন্তু app actually কাজ করছে কিনা বলে না।
  • HTTP Check: নির্দিষ্ট URL এ request পাঠিয়ে 200 OK আশা করে। App level check — বেশি reliable।
  • Custom Script: Database connection, disk space ইত্যাদি check করতে পারে। সাধারণত /health বা /ping endpoint ব্যবহার করুন।
nginx-health-check.conf
upstream backend {
    # Least connections algorithm
    least_conn;

    # Weighted servers — server1 বেশি powerful
    server 192.168.1.10:3000 weight=3;
    server 192.168.1.11:3000 weight=1;
    server 192.168.1.12:3000 weight=1;

    # Health check settings
    # max_fails: এতবার fail হলে server বাদ দিন
    # fail_timeout: এই সময়ের মধ্যে fail হলে count করুন
    server 192.168.1.13:3000 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;

    location / {
        proxy_pass http://backend;
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;

        # Health check endpoint
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # Active health check (Nginx Plus feature)
    # location /health {
    #     health_check interval=5s fails=3 passes=2;
    # }
}
005Tools

Popular Load Balancers — তুলনা

ToolTypeLayerPerformanceকখন ব্যবহার
NginxOpen SourceL7Excellentবেশিরভাগ web apps, reverse proxy
HAProxyOpen SourceL4+L7Industry BestHigh performance TCP, financial systems
AWS ALBManaged CloudL7ExcellentAWS microservices, containers
AWS NLBManaged CloudL4Ultra FastUltra-low latency, video streaming
Cloudflare LBCDN+LBL7GlobalGlobal apps, DDoS protection দরকার
TraefikOpen SourceL7GoodKubernetes, Docker environments
006Code Examples

Load Balancer Code Implementation

Concept বোঝার জন্য নিজে implement করে দেখা সবচেয়ে ভালো। নিচে Python এবং Node.js এ Load Balancer algorithms দেওয়া হলো।

load_balancer.py
import itertools
import requests
import threading
import time

class RoundRobinLoadBalancer:
    def __init__(self, servers: list[str]):
        self.servers = servers
        self.healthy_servers = list(servers)
        self._cycle = itertools.cycle(self.healthy_servers)
        self._lock = threading.Lock()

    def get_next_server(self) -> str | None:
        """Round Robin: পরবর্তী healthy server return করুন"""
        with self._lock:
            if not self.healthy_servers:
                return None  # সব server down!
            return next(self._cycle)

    def health_check(self):
        """প্রতি 5 সেকেন্ডে সব server check করুন"""
        while True:
            for server in self.servers:
                try:
                    response = requests.get(f"{server}/health", timeout=2)
                    if response.status_code == 200:
                        if server not in self.healthy_servers:
                            self.healthy_servers.append(server)
                            self._cycle = itertools.cycle(self.healthy_servers)
                            print(f"✅ {server} back online")
                except Exception:
                    if server in self.healthy_servers:
                        self.healthy_servers.remove(server)
                        self._cycle = itertools.cycle(self.healthy_servers)
                        print(f"❌ {server} removed — unhealthy")
            time.sleep(5)

    def forward_request(self, request_data: dict) -> dict:
        """Request কে next available server এ forward করুন"""
        server = self.get_next_server()
        if not server:
            return {"error": "No healthy servers available", "status": 503}
        try:
            response = requests.post(f"{server}/handle", json=request_data, timeout=10)
            return response.json()
        except Exception as e:
            return {"error": str(e), "status": 500}


# Usage
lb = RoundRobinLoadBalancer([
    "http://server1:3000",
    "http://server2:3000",
    "http://server3:3000",
])

# Background এ health check চালাও
health_thread = threading.Thread(target=lb.health_check, daemon=True)
health_thread.start()

# Request handle করুন
result = lb.forward_request({"user_id": 123, "action": "get_profile"})
leastConnections.js
class LeastConnectionsLB {
    constructor(servers) {
        // প্রতিটা server এর active connection count track করুন
        this.servers = servers.map(server => ({
            url: server,
            connections: 0,
            healthy: true,
        }));
    }

    getServer() {
        // শুধু healthy servers এর মধ্যে least connections ওয়ালাটা নাও
        const healthyServers = this.servers.filter(s => s.healthy);

        if (healthyServers.length === 0) {
            throw new Error('No healthy servers available');
        }

        // Least connections server খুঁজুন
        return healthyServers.reduce((min, server) =>
            server.connections < min.connections ? server : min
        );
    }

    async handleRequest(requestData) {
        const server = this.getServer();

        // Connection শুরু হলে count বাড়াও
        server.connections++;
        console.log(`Routing to ${server.url} (connections: ${server.connections})`);

        try {
            const response = await fetch(`${server.url}/handle`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(requestData),
            });
            return await response.json();
        } finally {
            // Request শেষ হলে count কমাও (success বা fail উভয় ক্ষেত্রে)
            server.connections--;
        }
    }

    markUnhealthy(serverUrl) {
        const server = this.servers.find(s => s.url === serverUrl);
        if (server) {
            server.healthy = false;
            console.log(`${serverUrl} marked as unhealthy`);
        }
    }

    markHealthy(serverUrl) {
        const server = this.servers.find(s => s.url === serverUrl);
        if (server) {
            server.healthy = true;
            server.connections = 0;
            console.log(`${serverUrl} back online`);
        }
    }
}

// Usage
const lb = new LeastConnectionsLB([
    'http://server1:3000',
    'http://server2:3000',
    'http://server3:3000',
]);

// Multiple concurrent requests — সবচেয়ে কম busy server পাবেন প্রতিটা
Promise.all([
    lb.handleRequest({ userId: 1 }),
    lb.handleRequest({ userId: 2 }),
    lb.handleRequest({ userId: 3 }),
]).then(results => console.log('All done:', results));
007Real World

Real World Use Cases

🎵 Spotify

AWS ALB (L7) ব্যবহার করে microservices routing এর জন্য। /stream/* → Streaming service, /search/* → Search service। Path-based routing দিয়ে হাজারো microservice manage করে।

🛍️ Shopify

Nginx + HAProxy combination। Black Friday তে traffic ১০x বাড়ে। HAProxy L4 দিয়ে initial connection, Nginx L7 দিয়ে content routing। Weighted Round Robin দিয়ে traffic ভাগ করে।

🎬 Netflix

Video streaming এর জন্য AWS NLB (L4) — ultra-low latency দরকার। API requests এর জন্য AWS ALB (L7)। দুটো আলাদা use case এর জন্য দুটো আলাদা Load Balancer।

🏦 Banks

IP Hash algorithm ব্যবহার করে session persistence এর জন্য। একবার login করলেন same server এ থাকো — session data consistent থাকে। Security এবং compliance এর জন্য critical।

008Interview Prep

Interview এ যা জিজ্ঞেস করে

Q1: L4 vs L7 — কখন কোনটা?

L4 ব্যবহার করুন যখন: Ultra-low latency দরকার (gaming, video streaming, financial trading)। HTTP content inspect করার দরকার নেই। Non-HTTP protocols (TCP/UDP) handle করতে হবে।

L7 ব্যবহার করুন যখন: Path-based routing দরকার (/api vs /web)। SSL termination করতে হবে। Microservices architecture। Cookie/header based routing।

Q2: Sticky Session কী এবং কেন problem?

Sticky Session (বা Session Affinity) মানে একই user কে সবসময় same server এ route করা। IP Hash algorithm এটা করে।

সমস্যা হলো: (১) Uneven load distribution — একটা server এ সব heavy users গেলে সে overloaded। (২) ঐ server down হলে user এর session হারিয়ে যায়। (৩) Horizontal scaling এর benefit কমে।

Better solution: Session data Redis এ রাখুন — যেকোনো server request handle করতে পারবেন।

Q3: Load Balancer নিজে Single Point of Failure না?

হ্যাঁ, এটা একটা valid concern। Solution হলো Load Balancer কেও redundant করা।

Active-Active: দুটো LB একসাথে কাজ করে, traffic ভাগ করে নেয়। একটা down হলে অন্যটা সব traffic নেয়।

Active-Passive: একটা primary, একটা standby। Primary down হলে automatically failover। AWS ALB/NLB এগুলো automatically managed — আপনাকে চিন্তা করতে হয় না।
009Lesson Summary

SUMMARY — আজকে যা শিখলাম

Conceptএক লাইনে
Load BalancerTraffic multiple servers এ distribute করে
L4 LBIP+Port দেখে route করে, ultra-fast কিন্তু content-blind
L7 LBHTTP content পড়ে smart routing করে, SSL terminate করে
Round RobinSequential server rotation — equal capacity এর জন্য
Least Connectionsসবচেয়ে কম busy server কে request দিন
IP HashSame client IP → Same server (session persistence)
Health CheckUnhealthy server automatically বাদ, ঠিক হলে ফিরিয়ে আনে
010Knowledge Check
011Assignments
012Practical Lab