Back to blog

Giải Thích Load Balancing

load-balancinginfrastructuredevopsbackendnetworkingperformance
Giải Thích Load Balancing

Giới Thiệu

Khi ứng dụng của bạn bắt đầu nhận được nhiều traffic hơn khả năng xử lý của một máy chủ, bạn có hai lựa chọn: nâng cấp máy chủ mạnh hơn (vertical scaling) hoặc thêm nhiều máy chủ hơn (horizontal scaling). Load balancing chính là thứ giúp horizontal scaling trở nên khả thi.

Một load balancer phân phối traffic mạng đến nhiều máy chủ, đảm bảo không có máy chủ nào bị quá tải. Đây là một trong những thành phần quan trọng nhất của hạ tầng cho bất kỳ ứng dụng production nào — từ web app nhỏ đến hệ thống phục vụ hàng triệu người dùng.

Bài hướng dẫn này bao gồm mọi thứ bạn cần biết về load balancing: cách hoạt động, các thuật toán đằng sau nó, các loại khác nhau, và cách triển khai với các công cụ thực tế.

Bạn Sẽ Học Được Gì

✅ Hiểu load balancing là gì và tại sao nó quan trọng
✅ Nắm vững các thuật toán load balancing (Round Robin, Least Connections, IP Hash, và nhiều hơn nữa)
✅ Phân biệt giữa Layer 4 và Layer 7 load balancing
✅ Triển khai health check và failover cho high availability
✅ Cấu hình session persistence và SSL termination
✅ Thiết lập load balancing với Nginx, HAProxy, và cloud providers
✅ Tìm hiểu các mô hình như Active-Active, Active-Passive, và Global Server Load Balancing


Load Balancing Là Gì?

Load balancing là quá trình phân phối traffic mạng đến đến nhiều máy chủ backend (còn gọi là server pool hoặc server farm) để đảm bảo:

  • Không có máy chủ nào bị quá tải với quá nhiều request
  • Tính khả dụng của ứng dụng luôn cao ngay cả khi một máy chủ gặp sự cố
  • Thời gian phản hồi luôn nhanh và ổn định cho tất cả người dùng

Không có load balancer, tất cả traffic đổ vào một máy chủ duy nhất:

1000 requests/giây → [Máy chủ duy nhất] → ❌ Quá tải, chậm, crash

Với load balancer:

1000 requests/giây → [Load Balancer] → [Server 1] ~333 req/s ✅
                                     → [Server 2] ~333 req/s ✅
                                     → [Server 3] ~333 req/s ✅

Tại Sao Cần Load Balancing?

Load balancing giải quyết nhiều vấn đề quan trọng:

Lợi íchKhông có Load BalancerCó Load Balancer
Tính khả dụngSingle point of failureVẫn hoạt động khi server gặp sự cố
Khả năng mở rộngGiới hạn ở một serverThêm server khi traffic tăng
Hiệu suấtGiảm dần khi tải tăngThời gian phản hồi ổn định
Bảo trìDowntime khi cập nhậtCập nhật cuốn chiếu không downtime
Hiệu quảServer có thể quá tải hoặc nhàn rỗiPhân phối đều công việc

Các Thuật Toán Load Balancing

Thuật toán xác định cách load balancer quyết định server nào sẽ xử lý mỗi request đến. Các thuật toán khác nhau phù hợp với các tình huống khác nhau.

1. Round Robin

Thuật toán đơn giản nhất. Các request được phân phối tuần tự qua các server theo thứ tự.

Request 1 → Server 1
Request 2 → Server 2
Request 3 → Server 3
Request 4 → Server 1  (lặp lại chu kỳ)
Request 5 → Server 2
Request 6 → Server 3

Cấu hình Nginx:

upstream backend {
    server 192.168.1.101;
    server 192.168.1.102;
    server 192.168.1.103;
}
 
server {
    location / {
        proxy_pass http://backend;
    }
}

Phù hợp nhất cho: Các server có cấu hình giống nhau và ứng dụng stateless.

Nhược điểm: Không tính đến tải của server — một request xử lý chậm trên Server 1 không ngăn việc gửi thêm request đến nó.

2. Weighted Round Robin

Giống Round Robin nhưng gán nhiều request hơn cho server mạnh hơn.

Server 1 (weight=5):  nhận 5 trong mỗi 8 request
Server 2 (weight=2):  nhận 2 trong mỗi 8 request
Server 3 (weight=1):  nhận 1 trong mỗi 8 request

Cấu hình Nginx:

upstream backend {
    server 192.168.1.101 weight=5;  # 8-core, 32GB RAM
    server 192.168.1.102 weight=2;  # 4-core, 16GB RAM
    server 192.168.1.103 weight=1;  # 2-core, 8GB RAM
}

Phù hợp nhất cho: Môi trường có các server với cấu hình khác nhau.

3. Least Connections

Gửi request đến server có ít kết nối active nhất.

Load balancer chọn Server 2 vì nó có ít kết nối active nhất.

Cấu hình Nginx:

upstream backend {
    least_conn;
    server 192.168.1.101;
    server 192.168.1.102;
    server 192.168.1.103;
}

Phù hợp nhất cho: Ứng dụng có thời gian xử lý request khác nhau (ví dụ: một số request mất 50ms, số khác mất 5 giây).

4. Weighted Least Connections

Kết hợp Least Connections với trọng số server. Server có tỷ lệ (kết nối active / weight) thấp nhất sẽ nhận request tiếp theo.

Server 1: 10 kết nối, weight=5 → tỷ lệ = 2.0
Server 2:  3 kết nối, weight=2 → tỷ lệ = 1.5 ✅ (được chọn)
Server 3:  4 kết nối, weight=1 → tỷ lệ = 4.0

Phù hợp nhất cho: Server có cấu hình khác nhau với thời gian xử lý request khác nhau.

5. IP Hash

Sử dụng địa chỉ IP của client để xác định server nào nhận request. Cùng một IP client luôn đến cùng một server.

Client 203.0.113.10 → hash → Server 2 (luôn luôn)
Client 198.51.100.5 → hash → Server 1 (luôn luôn)
Client 192.0.2.100  → hash → Server 3 (luôn luôn)

Cấu hình Nginx:

upstream backend {
    ip_hash;
    server 192.168.1.101;
    server 192.168.1.102;
    server 192.168.1.103;
}

Phù hợp nhất cho: Ứng dụng cần session persistence cơ bản mà không cần cookie hoặc quản lý session ở tầng ứng dụng.

Nhược điểm: Nếu một server bị down, tất cả client được hash đến server đó phải được phân phối lại, làm mất session của họ.

6. Least Response Time

Định tuyến đến server có thời gian phản hồi nhanh nhất và ít kết nối active nhất. Yêu cầu load balancer đo thời gian phản hồi một cách chủ động.

Phù hợp nhất cho: Ứng dụng yêu cầu hiệu suất cao, nơi bạn muốn người dùng được định tuyến đến server nhanh nhất.

7. Random

Chọn ngẫu nhiên một server cho mỗi request. Phân phối đều theo thống kê theo thời gian.

Phù hợp nhất cho: Pool server lớn, nơi sự đơn giản được ưu tiên và phân phối thống kê là đủ.

So Sánh Thuật Toán

Thuật toánXét tải serverSession PersistenceĐộ phức tạpTrường hợp sử dụng tốt nhất
Round Robin❌❌ThấpServer giống nhau, app stateless
Weighted Round Robin❌ (weight thủ công)❌ThấpServer cấu hình khác nhau
Least Connections✅❌Trung bìnhThời gian xử lý request khác nhau
IP Hash❌✅ThấpSession affinity cơ bản
Least Response Time✅❌CaoApp yêu cầu hiệu suất cao
Random❌❌ThấpPool lớn, đơn giản

Layer 4 vs Layer 7 Load Balancing

Load balancer hoạt động ở các tầng khác nhau của mô hình OSI. Hai tầng phổ biến nhất là Layer 4 (Transport) và Layer 7 (Application).

Layer 4 Load Balancing (Tầng Transport)

Hoạt động ở tầng TCP/UDP. Đưa ra quyết định định tuyến dựa trên:

  • IP nguồn và port
  • IP đích và port
  • Giao thức (TCP hoặc UDP)

Load balancer không kiểm tra nội dung của request (không HTTP header, URL, hay cookie).

Cách hoạt động:

  1. Client thiết lập kết nối TCP đến load balancer
  2. Load balancer chọn một backend server (sử dụng thuật toán đã chọn)
  3. Load balancer chuyển tiếp các gói TCP/UDP thô đến server được chọn
  4. Tất cả gói tin từ cùng một kết nối đi đến cùng một server

Ưu điểm:

  • Rất nhanh (không kiểm tra gói tin)
  • Overhead và latency thấp
  • Không phụ thuộc giao thức (hoạt động với HTTP, SMTP, FTP, database, v.v.)

Nhược điểm:

  • Không thể định tuyến dựa trên URL, header, hoặc nội dung
  • Không thể sửa đổi request hoặc response
  • Khả năng health check hạn chế

Layer 7 Load Balancing (Tầng Application)

Hoạt động ở tầng HTTP/HTTPS. Đưa ra quyết định định tuyến dựa trên:

  • Đường dẫn URL (ví dụ: /api/* vs /static/*)
  • HTTP header (ví dụ: Host, User-Agent, Cookie)
  • Phương thức HTTP (GET, POST, v.v.)
  • Query parameter
  • Nội dung body của request

Ví dụ định tuyến dựa trên nội dung với Nginx:

upstream api_servers {
    server 192.168.1.101;
    server 192.168.1.102;
}
 
upstream static_servers {
    server 192.168.1.201;
    server 192.168.1.202;
}
 
server {
    listen 80;
 
    location /api/ {
        proxy_pass http://api_servers;
    }
 
    location /static/ {
        proxy_pass http://static_servers;
    }
 
    location /images/ {
        proxy_pass http://static_servers;
    }
}

Ưu điểm:

  • Quyết định định tuyến nhận biết nội dung
  • Có thể sửa đổi request/response (thêm header, viết lại URL)
  • Health check nâng cao (HTTP status code, nội dung response)
  • SSL termination
  • Caching, nén, và rate limiting

Nhược điểm:

  • Latency cao hơn (phải phân tích HTTP)
  • Tốn tài nguyên hơn
  • Chỉ HTTP/HTTPS (không phù hợp cho giao thức TCP tùy ý)

Bảng So Sánh

Tính năngLayer 4Layer 7
Tầng OSITransport (TCP/UDP)Application (HTTP/HTTPS)
Định tuyến dựa trênIP, port, giao thứcURL, header, cookie, nội dung
Hiệu suấtNhanh hơn (không kiểm tra)Chậm hơn (phân tích HTTP)
Nhận biết nội dung❌✅
SSL TerminationChỉ pass-through✅ Termination đầy đủ
Định tuyến URL❌✅
Thao tác Header❌✅
Caching❌✅
Giao thứcMọi TCP/UDPHTTP/HTTPS
Trường hợp sử dụngThroughput cao, LB databaseWeb app, API, microservices

Khi Nào Sử Dụng Loại Nào

Chọn Layer 4 khi:

  • Bạn cần hiệu suất tối đa với latency tối thiểu
  • Bạn load balancing các giao thức không phải HTTP (database, SMTP, gaming server)
  • Bạn không cần định tuyến dựa trên nội dung

Chọn Layer 7 khi:

  • Bạn cần định tuyến dựa trên URL path, header, hoặc cookie
  • Bạn muốn SSL termination tại load balancer
  • Bạn cần các tính năng nâng cao như caching, nén, hoặc rate limiting
  • Bạn đang xây dựng microservices với các backend khác nhau cho các path khác nhau

Health Check và Failover

Load balancer phải biết server nào đang healthy và có khả năng xử lý request. Health check là các probe định kỳ gửi đến backend server để xác minh chúng đang hoạt động và chức năng bình thường.

Các Loại Health Check

1. TCP Health Check (Layer 4)

Đơn giản kiểm tra xem server có chấp nhận kết nối TCP trên port được chỉ định không.

Load Balancer → TCP SYN → Server:8080
Server:8080  → TCP SYN-ACK → ✅ Healthy

2. HTTP Health Check (Layer 7)

Gửi một HTTP request đến health endpoint và kiểm tra response status code.

Load Balancer → GET /health → Server:8080
Server:8080  → 200 OK → ✅ Healthy
Server:8080  → 503 Service Unavailable → ❌ Unhealthy

Triển khai health endpoint phổ biến:

// Express.js health check endpoint
app.get('/health', async (req, res) => {
  try {
    // Kiểm tra kết nối database
    await db.query('SELECT 1');
 
    // Kiểm tra kết nối Redis
    await redis.ping();
 
    res.status(200).json({
      status: 'healthy',
      uptime: process.uptime(),
      timestamp: new Date().toISOString(),
    });
  } catch (error) {
    res.status(503).json({
      status: 'unhealthy',
      error: error.message,
    });
  }
});
// Spring Boot Actuator (health endpoint tự động cấu hình)
// GET /actuator/health → { "status": "UP" }
 
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
    @Override
    public Health health() {
        if (isDatabaseReachable()) {
            return Health.up()
                .withDetail("database", "PostgreSQL")
                .build();
        }
        return Health.down()
            .withDetail("error", "Cannot reach database")
            .build();
    }
}

3. Script-based Health Check

Chạy script tùy chỉnh thực hiện các kiểm tra phức tạp (dung lượng ổ đĩa, bộ nhớ, logic ứng dụng).

Cấu Hình Health Check Nginx

upstream backend {
    server 192.168.1.101;
    server 192.168.1.102;
    server 192.168.1.103;
 
    # Passive health check (Nginx OSS)
    # Đánh dấu server down sau 3 lần thất bại, thử lại sau 30 giây
}
 
server {
    location / {
        proxy_pass http://backend;
        proxy_next_upstream error timeout http_500 http_502 http_503;
        proxy_connect_timeout 5s;
        proxy_read_timeout 10s;
    }
}

Cấu Hình Health Check HAProxy

backend web_servers
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
 
    server srv1 192.168.1.101:8080 check inter 5s fall 3 rise 2
    server srv2 192.168.1.102:8080 check inter 5s fall 3 rise 2
    server srv3 192.168.1.103:8080 check inter 5s fall 3 rise 2

Giải thích các tham số:

  • inter 5s: Kiểm tra mỗi 5 giây
  • fall 3: Đánh dấu unhealthy sau 3 lần thất bại liên tiếp
  • rise 2: Đánh dấu healthy lại sau 2 lần thành công liên tiếp

Chiến Lược Failover

Khi một server không qua health check, load balancer phải xử lý:

Graceful degradation: Khi server gặp sự cố, các server còn lại gánh thêm tải:

Bình thường: Server A (33%) | Server B (33%) | Server C (33%)
Server C ❌:  Server A (50%) | Server B (50%) | Server C (down)
Server B ❌:  Server A (100%) | Server B (down) | Server C (down)

Session Persistence (Sticky Sessions)

Mặc định, load balancer có thể định tuyến các request liên tiếp từ cùng một người dùng đến các server khác nhau. Đây là vấn đề khi ứng dụng lưu session data trong bộ nhớ server.

Vấn Đề

Request 1: User đăng nhập → Server A (session lưu trong bộ nhớ Server A)
Request 2: User tải dashboard → Server B (không tìm thấy session → ❌ chuyển hướng đến trang đăng nhập)

Giải Pháp

1. Sticky Sessions (Dựa trên Cookie)

Load balancer chèn một cookie để gắn người dùng vào server cụ thể.

upstream backend {
    server 192.168.1.101;
    server 192.168.1.102;
 
    # Nginx Plus (thương mại) sticky cookie
    sticky cookie srv_id expires=1h domain=.example.com path=/;
}

HAProxy sticky sessions:

backend web_servers
    balance roundrobin
    cookie SERVERID insert indirect nocache
 
    server srv1 192.168.1.101:8080 cookie s1 check
    server srv2 192.168.1.102:8080 cookie s2 check

2. IP Hash (như đã thảo luận ở trên)

Định tuyến theo IP client — cùng một IP luôn đến cùng một server.

3. Externalized Sessions (Khuyến nghị)

Thay vì dựa vào sticky sessions, lưu session bên ngoài để bất kỳ server nào cũng có thể xử lý bất kỳ request nào:

// Express.js với Redis session store
import session from 'express-session';
import RedisStore from 'connect-redis';
import { createClient } from 'redis';
 
const redisClient = createClient({ url: 'redis://redis-host:6379' });
await redisClient.connect();
 
app.use(session({
  store: new RedisStore({ client: redisClient }),
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: { secure: true, maxAge: 86400000 }, // 24 giờ
}));

Tại sao externalized sessions tốt hơn:

  • Bất kỳ server nào cũng xử lý được bất kỳ request nào (stateless thực sự)
  • Server gặp sự cố không mất session người dùng
  • Dễ dàng mở rộng theo chiều ngang
  • Không phức tạp sticky session

So Sánh Session Persistence

Cách tiếp cậnẢnh hưởng khi server lỗiKhả năng mở rộngĐộ phức tạp
Sticky Sessions (Cookie)Mất session khi server dieHạn chếThấp
IP HashMất session khi server dieHạn chếThấp
External Store (Redis)Không ảnh hưởng — session vẫn cònXuất sắcTrung bình
JWT Token (Stateless)Không ảnh hưởng — không có state trên serverXuất sắcTrung bình

SSL/TLS Termination

SSL termination có nghĩa là load balancer xử lý việc mã hóa/giải mã traffic HTTPS, nên các backend server nhận HTTP thuần.

Tại Sao Terminate SSL Tại Load Balancer?

Lợi ích:

  • Giảm tải server: Mã hóa/giải mã tốn CPU. Chuyển nó cho load balancer giải phóng backend server cho logic ứng dụng.
  • Quản lý certificate tập trung: Quản lý SSL certificate ở một nơi thay vì mỗi server.
  • Backend đơn giản hơn: Server không cần cấu hình SSL.

Nginx SSL termination:

server {
    listen 443 ssl;
    server_name example.com;
 
    ssl_certificate     /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
 
    location / {
        proxy_pass http://backend;  # HTTP thuần đến backend
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }
}

SSL Pass-through vs Termination vs Re-encryption

Chế độMô tảBackend nhậnTrường hợp sử dụng
TerminationLB giải mã, gửi HTTP đến backendHTTP thuầnHầu hết web application
Pass-throughLB chuyển tiếp traffic mã hóa nguyên bảnHTTPS (phải xử lý SSL)Yêu cầu mã hóa end-to-end
Re-encryptionLB giải mã, sau đó mã hóa lại đến backendHTTPS (mã hóa lại)Yêu cầu compliance

Các Load Balancer Phổ Biến

Software Load Balancer

1. Nginx

Web server và reverse proxy phổ biến nhất, cũng được sử dụng rộng rãi làm load balancer.

# Cấu hình load balancer Nginx hoàn chỉnh
upstream api_backend {
    least_conn;
    server 10.0.1.101:8080 weight=3;
    server 10.0.1.102:8080 weight=2;
    server 10.0.1.103:8080 weight=1;
    server 10.0.1.104:8080 backup;  # Chỉ dùng khi server khác down
}
 
server {
    listen 443 ssl http2;
    server_name api.example.com;
 
    ssl_certificate     /etc/ssl/certs/api.example.com.crt;
    ssl_certificate_key /etc/ssl/private/api.example.com.key;
 
    location / {
        proxy_pass http://api_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
 
        # Timeout
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
        proxy_send_timeout 30s;
 
        # Thử lại khi thất bại
        proxy_next_upstream error timeout http_502 http_503;
        proxy_next_upstream_tries 3;
    }
}

Điểm mạnh: Nhẹ, hiệu suất cao, hệ sinh thái phong phú, tài liệu xuất sắc.

2. HAProxy

Load balancer TCP/HTTP hiệu suất cao, được thiết kế chuyên dụng.

# Cấu hình HAProxy
global
    log     stdout format raw local0
    maxconn 4096
 
defaults
    mode    http
    timeout connect 5s
    timeout client  30s
    timeout server  30s
    option  httplog
 
frontend http_front
    bind *:80
    bind *:443 ssl crt /etc/ssl/certs/example.pem
    redirect scheme https if !{ ssl_fc }
 
    # Định tuyến dựa trên URL path
    acl is_api path_beg /api
    acl is_static path_beg /static /images /css /js
 
    use_backend api_servers if is_api
    use_backend static_servers if is_static
    default_backend web_servers
 
backend web_servers
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
    server web1 10.0.1.101:8080 check inter 5s fall 3 rise 2
    server web2 10.0.1.102:8080 check inter 5s fall 3 rise 2
 
backend api_servers
    balance leastconn
    option httpchk GET /api/health
    server api1 10.0.2.101:3000 check inter 5s fall 3 rise 2
    server api2 10.0.2.102:3000 check inter 5s fall 3 rise 2
 
backend static_servers
    balance roundrobin
    server static1 10.0.3.101:80 check
    server static2 10.0.3.102:80 check

Điểm mạnh: Được xây dựng cho load balancing, dashboard thống kê xuất sắc, latency rất thấp, health check nâng cao, được GitHub, Stack Overflow, và Reddit sử dụng.

3. Traefik

Reverse proxy và load balancer hiện đại, cloud-native với khả năng tự động phát hiện dịch vụ.

# docker-compose.yml với Traefik
services:
  traefik:
    image: traefik:v3.0
    command:
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "[email protected]"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - letsencrypt:/letsencrypt
 
  api:
    image: my-api:latest
    deploy:
      replicas: 3
    labels:
      - "traefik.http.routers.api.rule=Host(`api.example.com`)"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"
      - "traefik.http.services.api.loadbalancer.server.port=3000"
 
volumes:
  letsencrypt:

Điểm mạnh: Tự động phát hiện dịch vụ với Docker/Kubernetes, tích hợp Let's Encrypt sẵn có, cấu hình động không cần restart.

So Sánh Software Load Balancer

Tính năngNginxHAProxyTraefik
Mục đích chínhWeb server + LBLB chuyên dụngLB cloud-native
Layer 4✅✅✅
Layer 7✅✅✅
Cấu hìnhFile-basedFile-basedFile, Docker label, API
Tự phát hiện❌ (thủ công)❌ (thủ công)✅ (Docker, K8s)
Let's EncryptQua certbotQua ACME✅ Tích hợp sẵn
DashboardChỉ Nginx Plus✅ Trang stats✅ Web UI
Hot Reload✅ nginx -s reload✅ haproxy -sf✅ Tự động
Được dùng bởi~34% websiteGitHub, RedditTổ chức dùng Docker nhiều

Cloud Load Balancer

Cloud provider cung cấp load balancer được quản lý, không cần quản lý server:

AWS:

  • Application Load Balancer (ALB): Layer 7, định tuyến dựa trên nội dung, hỗ trợ WebSocket
  • Network Load Balancer (NLB): Layer 4, latency cực thấp, hàng triệu request mỗi giây
  • Classic Load Balancer (CLB): Legacy, hỗ trợ cả L4 và L7

Google Cloud:

  • Cloud Load Balancing: Global, dựa trên anycast, tự động mở rộng, hỗ trợ HTTP(S), TCP, UDP

Azure:

  • Azure Load Balancer: Layer 4
  • Application Gateway: Layer 7 với WAF (Web Application Firewall)

Khi nào dùng cloud vs software load balancer:

Tình huốngKhuyến nghị
Chạy trên một cloud providerDùng cloud LB (quản lý sẵn, tự mở rộng)
Multi-cloud hoặc hybridSoftware LB (Nginx, HAProxy)
Môi trường KubernetesCloud LB + Ingress Controller (Nginx, Traefik)
Tiết kiệm chi phí, self-hostedNginx hoặc HAProxy trên VPS
Cần kiểm soát chi tiếtSoftware LB với cấu hình tùy chỉnh

Load Balancing Trong Microservices

Trong kiến trúc microservices, load balancing trở nên càng quan trọng hơn khi các service liên tục giao tiếp với nhau.

Load Balancing Giữa Các Service

Client-Side vs Server-Side Load Balancing

Server-side load balancing (truyền thống): Một load balancer chuyên dụng nằm giữa các service.

Service A → Load Balancer → Service B (instance 1)
                          → Service B (instance 2)
                          → Service B (instance 3)

Client-side load balancing: Service gọi tự chọn instance nào để gọi, sử dụng service registry.

Service A → [Service Registry] → biết tất cả instance của Service B
          → gọi trực tiếp Service B (instance 2)

Ví dụ client-side (khái niệm):

class ClientSideLoadBalancer {
  private instances: string[];
  private currentIndex = 0;
 
  constructor(private serviceRegistry: ServiceRegistry) {
    this.instances = [];
  }
 
  async getNextInstance(serviceName: string): Promise<string> {
    // Làm mới danh sách instance từ service registry
    this.instances = await this.serviceRegistry.getInstances(serviceName);
 
    if (this.instances.length === 0) {
      throw new Error(`Không có instance nào cho ${serviceName}`);
    }
 
    // Round Robin
    const instance = this.instances[this.currentIndex % this.instances.length];
    this.currentIndex++;
    return instance;
  }
}

Service Discovery

Để load balancing trong microservices, các service cần tìm thấy nhau. Đây gọi là service discovery.

DNS-based discovery:

# Kubernetes Service (DNS-based discovery tích hợp sẵn)
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
    - port: 80
      targetPort: 3000
  type: ClusterIP
---
# Các service khác có thể gọi: http://user-service/api/users
# Kubernetes DNS phân giải đến các pod IP healthy

Registry-based discovery (Consul, Eureka, etcd):

Service B khởi động → đăng ký với Consul: "user-service tại 10.0.1.5:3000"
Service A cần Service B → hỏi Consul: "user-service ở đâu?"
Consul trả lời: ["10.0.1.5:3000", "10.0.1.6:3000", "10.0.1.7:3000"]
Service A chọn một → gọi 10.0.1.6:3000

DNS-Based Load Balancing

DNS có thể thực hiện load balancing cơ bản bằng cách trả về các địa chỉ IP khác nhau cho cùng một tên miền.

Cách Hoạt Động

Client → DNS query: "api.example.com" → DNS server
DNS server → Response: [203.0.113.1, 203.0.113.2, 203.0.113.3]
Client → Kết nối đến 203.0.113.1 (thường là IP đầu tiên)

Query tiếp theo (từ client khác hoặc cùng client, sau khi TTL hết hạn):

DNS server → Response: [203.0.113.2, 203.0.113.3, 203.0.113.1]  (xoay vòng)

Cấu Hình DNS Round Robin

; File zone DNS BIND
api.example.com.    300    IN    A    203.0.113.1
api.example.com.    300    IN    A    203.0.113.2
api.example.com.    300    IN    A    203.0.113.3

Hạn Chế Của DNS Load Balancing

Hạn chếẢnh hưởng
DNS cachingClient và resolver cache response DNS. Thay đổi mất thời gian để lan truyền (dựa trên TTL).
Không có health checkDNS không biết server có down không. Client có thể kết nối đến server đã chết.
Không nhận biết sessionKhông kiểm soát được server nào xử lý client nào.
Phân phối không đềuMột số client cache lâu hơn, dẫn đến tải không đều.

Khi nào DNS load balancing hữu ích:

  • Phân phối traffic qua các vùng địa lý (GSLB)
  • Là tầng đầu tiên trước load balancer chuyên dụng
  • Setup đơn giản nơi health check không quan trọng

Global Server Load Balancing (GSLB)

GSLB phân phối traffic qua các server ở nhiều vị trí địa lý để giảm thiểu latency và cung cấp disaster recovery.

Cách GSLB Hoạt Động

  1. User thực hiện DNS query cho app.example.com
  2. DNS hỗ trợ GSLB xem xét:
    • Vị trí địa lý của user
    • Health của mỗi data center
    • Tải hiện tại tại mỗi location
    • Latency đến mỗi data center
  3. Trả về IP của data center gần nhất/tốt nhất

Chiến Lược Định Tuyến GSLB

Chiến lượcMô tảTrường hợp sử dụng
GeolocationĐịnh tuyến theo quốc gia/vùng của clientCompliance, nội dung bản địa hóa
Latency-basedĐịnh tuyến đến data center latency thấp nhấtTối ưu hiệu suất
FailoverData center chính/phụDisaster recovery
WeightedPhân phối phần trăm traffic cho mỗi vùngDi chuyển dần dần, canary deployment

Dịch Vụ GSLB Cloud

  • AWS Route 53: Latency-based, geolocation, failover, weighted routing
  • Google Cloud DNS: Geolocation routing với health check
  • Azure Traffic Manager: Performance, weighted, priority, geographic routing
  • Cloudflare Load Balancing: Dựa trên anycast với geo-steering

Auto-Scaling Với Load Balancer

Load balancer kết hợp với auto-scaling để xử lý traffic spike tự động.

Cách Auto-Scaling Hoạt Động

Trigger mở rộng:

  • CPU sử dụng > 70% trong 5 phút
  • Bộ nhớ sử dụng > 80%
  • Số request > 1000/giây mỗi server
  • Thời gian phản hồi > 500ms trung bình

Kubernetes Horizontal Pod Autoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

AWS Auto Scaling Group

Load Balancer (ALB)
  ↓
Auto Scaling Group
  ├── Min: 2 instance
  ├── Desired: 3 instance
  ├── Max: 10 instance
  └── Scaling Policy:
      ├── Scale Up: CPU > 70% trong 5 phút → thêm 2 instance
      └── Scale Down: CPU < 30% trong 15 phút → bớt 1 instance

Best practice cho auto-scaling:

  • Đặt ngưỡng scale-up thận trọng (phản ứng nhanh với traffic spike)
  • Đặt ngưỡng scale-down tích cực (scale down chậm để tránh flapping)
  • Luôn có số lượng instance healthy tối thiểu
  • Sử dụng health check để đảm bảo instance mới sẵn sàng trước khi nhận traffic

Các Mô Hình Load Balancing

Active-Active

Tất cả server đều đang xử lý traffic đồng thời.

Load Balancer
├── Server A (Active) ← xử lý request
├── Server B (Active) ← xử lý request
└── Server C (Active) ← xử lý request

Ưu điểm: Tận dụng tối đa tài nguyên, throughput cao nhất.

Nhược điểm: Tất cả server cần cấu hình giống nhau, phức tạp hơn để bảo trì.

Active-Passive (Failover)

Chỉ server active xử lý traffic. Server passive là standby, tiếp quản khi server active gặp sự cố.

Bình thường:
Load Balancer → Server A (Active) ← xử lý tất cả request
                Server B (Passive/Standby) ← nhàn rỗi, giám sát
 
Failover:
Load Balancer → Server A (Down) ✗
                Server B (Giờ là Active) ← tiếp quản

Ưu điểm: Đơn giản, đảm bảo khả năng failover.

Nhược điểm: Server passive nhàn rỗi (lãng phí tài nguyên).

Blue-Green Deployment Với Load Balancer

Sử dụng load balancing để triển khai không downtime:

Bước 1: Blue (v1) đang live
Load Balancer → Blue Servers (v1) ✅
 
Bước 2: Deploy Green (v2), kiểm thử
Load Balancer → Blue Servers (v1) ✅
                Green Servers (v2) [đang kiểm thử]
 
Bước 3: Chuyển traffic sang Green
Load Balancer → Green Servers (v2) ✅
                Blue Servers (v1) [standby cho rollback]

Canary Deployment

Định tuyến một tỷ lệ nhỏ traffic đến version mới:

upstream backend {
    server 10.0.1.101:8080 weight=9;   # v1 (90% traffic)
    server 10.0.1.102:8080 weight=1;   # v2 (10% traffic — canary)
}

Tăng dần weight canary khi độ tin cậy tăng:

Giai đoạn 1:  v1 = 90%, v2 = 10%  → theo dõi metrics
Giai đoạn 2:  v1 = 70%, v2 = 30%  → theo dõi metrics
Giai đoạn 3:  v1 = 50%, v2 = 50%  → theo dõi metrics
Giai đoạn 4:  v1 = 0%,  v2 = 100% → rollout hoàn tất

Giám Sát và Metrics

Load balancer tạo ra các metrics giá trị để hiểu về health và hiệu suất hệ thống.

Các Metrics Quan Trọng Cần Giám Sát

MetricCho biết điều gìNgưỡng cảnh báo
Request rateLượng traffic (req/s)Tăng hoặc giảm đột ngột
Error rateTỷ lệ response 4xx/5xx> 1% tổng traffic
Latency (p50, p95, p99)Phân bố thời gian phản hồip99 > 1 giây
Active connectionsKết nối đồng thời hiện tạiGần đến giới hạn server
Backend healthSố server healthy vs unhealthyBất kỳ server nào down
BandwidthDữ liệu truyền vào/raGần đến giới hạn mạng
Connection queueRequest đang chờ serverQueue > 0 kéo dài

Giám Sát Nginx Status

# Bật Nginx stub status
server {
    listen 8080;
    location /nginx_status {
        stub_status on;
        allow 10.0.0.0/8;    # Chỉ cho phép mạng nội bộ
        deny all;
    }
}
# Output
Active connections: 291
server accepts handled requests
 16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106

HAProxy Stats Dashboard

listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if TRUE
    stats auth admin:password

HAProxy cung cấp web dashboard tích hợp hiển thị metrics thời gian thực cho mỗi backend server: kết nối, tốc độ request, thời gian phản hồi, trạng thái health, và tỷ lệ lỗi.


Best Practices

Best Practice Cấu Hình

1. Luôn cấu hình health check

# Đừng chỉ kiểm tra port có mở không — kiểm tra health ứng dụng
location /health {
    proxy_pass http://backend/health;
    proxy_connect_timeout 2s;
    proxy_read_timeout 2s;
}

2. Đặt timeout phù hợp

proxy_connect_timeout 5s;    # Thời gian thiết lập kết nối đến backend
proxy_read_timeout 30s;      # Thời gian chờ response từ backend
proxy_send_timeout 10s;      # Thời gian gửi request đến backend

3. Truyền thông tin client đến backend

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

4. Cấu hình giới hạn kết nối

upstream backend {
    server 192.168.1.101 max_conns=100;
    server 192.168.1.102 max_conns=100;
    queue 50 timeout=10s;  # Xếp hàng request khi tất cả server đạt max
}

Best Practice Kiến Trúc

1. Loại bỏ load balancer khỏi single point of failure

Sử dụng load balancer dự phòng với failover:

          ┌── Load Balancer 1 (Active)
Virtual IP ──┤
          └── Load Balancer 2 (Standby)
                    │
            ┌───────┼───────┐
          Server  Server  Server

2. Sử dụng đúng thuật toán cho workload

  • Stateless API: Round Robin hoặc Least Connections
  • WebSocket connections: IP Hash hoặc Least Connections
  • Server kích cỡ khác nhau: Weighted Round Robin
  • Yêu cầu hiệu suất cao: Least Response Time

3. Externalize session state

Không dựa vào sticky sessions. Sử dụng Redis, Memcached, hoặc JWT token cho quản lý session.

4. Bật connection keep-alive

upstream backend {
    server 192.168.1.101;
    keepalive 32;  # Giữ 32 kết nối idle cho mỗi backend
}
 
location / {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Connection "";  # Bật keepalive đến backend
}

5. Lên kế hoạch graceful shutdown

Khi gỡ server để bảo trì:

1. Đánh dấu server "draining" (ngừng kết nối mới)
2. Chờ các kết nối hiện tại hoàn thành
3. Gỡ server khỏi pool
4. Thực hiện bảo trì
5. Thêm lại server vào pool
6. Giám sát health check xác nhận nó healthy

Các Lỗi Thường Gặp

LỗiVấn đềGiải pháp
Không có health checkTraffic gửi đến server đã chếtLuôn cấu hình health endpoint
Load balancer đơnLB trở thành single point of failureDeploy LB dự phòng với failover
Sticky sessions khắp nơiHạn chế khả năng mở rộng, failover phức tạpDùng external session store (Redis)
Bỏ qua timeoutBackend chậm block tất cả kết nốiĐặt connect, read, và send timeout
Không giám sátVấn đề được phát hiện bởi user, không phải engineerGiám sát request rate, error, latency
Cấu hình SSL saiMixed content, cảnh báo bảo mậtTerminate SSL tại LB, redirect HTTP sang HTTPS
Không giới hạn kết nốiMột backend bị quá tải do burstĐặt max_conns cho mỗi server
Không graceful shutdownRequest active bị drop khi deployDrain kết nối trước khi gỡ server

Tóm Tắt và Điểm Chính

✅ Load balancing phân phối traffic qua nhiều server cho khả năng mở rộng, tính khả dụng, và hiệu suất
✅ Thuật toán như Round Robin, Least Connections, và IP Hash xác định cách traffic được định tuyến
✅ Layer 4 load balancing nhanh hơn nhưng không nhận biết nội dung; Layer 7 cho phép định tuyến dựa trên URL, header, và cookie
✅ Health check là thiết yếu — luôn cấu hình để phát hiện và gỡ bỏ server unhealthy
✅ Externalize session state (Redis, JWT) thay vì dựa vào sticky sessions
✅ SSL termination tại load balancer đơn giản hóa quản lý certificate và giảm tải backend
✅ Nginx và HAProxy là software load balancer phổ biến nhất; cloud provider cung cấp giải pháp managed
✅ Auto-scaling kết hợp với load balancer để xử lý traffic spike tự động
✅ Giám sát request rate, error rate, latency, và backend health liên tục
✅ Deploy load balancer dự phòng để tránh single point of failure


Tiếp Theo

Bây giờ bạn đã hiểu load balancing, hãy khám phá các chủ đề liên quan:


Load balancing là một trong những quyết định hạ tầng có ảnh hưởng lớn nhất mà bạn sẽ đưa ra. Bắt đầu với setup Round Robin đơn giản, thêm health check, externalize session, và mở rộng từ đó. Bạn không cần triển khai mọi thứ ngay ngày đầu — nhưng bạn cần lên kế hoạch cho nó.

📬 Đăng ký nhận bản tin

Nhận những bài viết mới nhất qua email mỗi tuần. Không spam, hủy đăng ký bất cứ lúc nào.

Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất cứ lúc nào.

💬 Comments

Đăng nhập để bình luận

Chúng tôi sẽ không đăng bất cứ điều gì mà không có sự cho phép của bạn.