Hành trình của một Request: Từ Proxy, Load Balancer đến API Gateway
Khi bạn gõ một địa chỉ web và nhấn Enter, cảm giác rất kỳ diệu: trình duyệt hỏi, server đáp, mọi thứ xong xuôi trong chớp mắt. Nhưng phía sau hậu trường, request của bạn không hề đi "đường thẳng". Nó phải chạy qua một loạt các "trạm trung chuyển" trước khi chạm đến đích: phân giải DNS (đã là một tầng chia tải), định tuyến anycast tới PoP gần nhất, CDN trả lời luôn nếu là nội dung tĩnh, rồi mới tới lượt các trạm bên trong hệ thống.
Bài viết này sẽ tập trung vào phần "bên trong": proxy, load balancer, API gateway — những trạm sau khi request đã tới được hệ thống của bạn.
Mỗi công cụ sinh ra để giải quyết đúng "nỗi đau" mà giai đoạn trước để lại:
| Giai đoạn | Hệ thống của bạn | Thứ bạn cần |
|---|---|---|
| 1 | Một server duy nhất | Proxy / Reverse Proxy |
| 2 | Nhiều server giống nhau | Load Balancer (L4 / L7) |
| 3 | Chia nhỏ thành Microservices | API Gateway |
| 4 | Dữ liệu quá lớn, phải chia máy | Consistent Hashing |
Chúng ta hãy cùng bóc tách từng trạm một nhé.
Phần 1. Proxy — Những "Người gác cổng" của Internet
Dù mang tên gì, bản chất của mọi loại proxy đều làm đúng một việc: đứng ở giữa để đánh chặn (intercept) và chuyển tiếp (forward) request. Điểm khác biệt duy nhất — nằm ở câu hỏi: nó quay mặt về phía ai ?
- Nếu nó quay mặt về phía người dùng — giúp giấu họ, hoặc kiểm soát họ đi đâu — đó là Forward Proxy.
- Nếu nó quay mặt về phía hệ thống của mình — bảo vệ server, gánh việc nặng, chia traffic — đó là Reverse Proxy.
1.1 Forward Proxy — đại diện cho phía Client
Forward Proxy là server đứng giữa máy tính của bạn và mạng Internet.
[Bạn] --> [Forward Proxy] --> [ Internet ] --> [Website]
Khi bạn lướt web qua Forward Proxy, trang web đầu bên kia chỉ nhìn thấy IP của proxy chứ không thấy IP thật của bạn. Tuy nhiên, proxy không đồng nghĩa với ẩn danh hoàn toàn: nó có thể gửi IP gốc qua header như X-Forwarded-For, trong khi cookie và fingerprint trình duyệt vẫn có thể nhận diện bạn. Hơn nữa, proxy vẫn biết bạn là ai và đang truy cập gì — bạn chỉ đang chuyển niềm tin từ website sang chủ sở hữu proxy.
Trong các doanh nghiệp, người ta hay dùng Transparent Proxy. Cơ chế của nó là: việc bẻ hướng traffic diễn ra ở tầng Network (router đẩy toàn bộ port 80/443 sang proxy bằng policy routing hoặc iptables -j REDIRECT), nhưng bản thân proxy vẫn đọc HTTP ở tầng 7 để lọc URL. Nhờ vậy nó ép được toàn bộ thiết bị trong công ty tuân thủ luật kiểm duyệt mạng mà không cần cấu hình thủ công trên từng máy — nhân viên thậm chí không biết là traffic của mình đang đi qua proxy.
1.2 Reverse Proxy — Vệ sĩ của Server
Reverse Proxy thì lật ngược ván cờ lại. Nó đứng giữa Internet và cụm server của bạn, thay mặt hệ thống đứng ra hứng mọi "viên đạn" (request) từ bên ngoài bắn vào. Client không biết mình đang nói chuyện với ai phía sau.
[Client] --> [ Internet ] --> [Reverse Proxy] --> [Server của bạn]
Đây là thành phần bạn sẽ gặp trong gần như mọi hệ thống production, vì nó gánh cùng lúc bốn việc:
- Che giấu mục tiêu: Backend không có public IP, chỉ nằm trong private subnet. Kẻ tấn công không có mục tiêu trực tiếp để nhắm DDoS.
- Đỡ đạn SSL (SSL Termination): Lý do không đơn giản là "giải mã HTTPS tốn CPU". Với CPU hiện đại có hardware acceleration như AES-NI, symmetric encryption/decryption tương đối rẻ. Chi phí đáng chú ý hơn thường nằm ở việc thiết lập connection mới và TLS handshake. Lý do chính để terminate TLS tại Reverse Proxy là:
- Quản lý certificate tập trung: chỉ cần gia hạn và quản lý certificate tại một nơi thay vì từng service.
- Tái sử dụng kết nối — proxy giữ sẵn connection pool keep-alive tới backend, backend không phải handshake lại liên tục.
3. Phân tải nhẹ (Load Balancing): Chia đều khách cho các server phía sau.
4. Caching: Nhớ sẵn các nội dung tĩnh (ảnh, CSS) và trả về luôn cho khách mà không làm phiền backend.
Tóm lại: Forward Proxy đại diện cho phía Client. Reverse Proxy đại diện cho phía Server.
Phần 2. Load Balancer — chia tải ở tầng nào?
Đến đây dễ nảy ra một câu hỏi: Reverse Proxy đã chia tải được rồi, vậy Load Balancer là con gì khác?
Câu trả lời hơi phản trực giác: không khác. Nginx, HAProxy, Envoy vừa là Reverse Proxy vừa là Load Balancer — đó là hai vai trò trên cùng một tiến trình, không phải hai thiết bị. "Reverse Proxy" mô tả việc nó đứng thay mặt server; "Load Balancer" mô tả việc nó chia request cho nhiều server.
Vậy thứ thực sự phân biệt là gì? Là nó đọc được đến tầng nào của gói tin — và từ đó, nó chia tải dựa trên thông tin gì.
- Chỉ đọc IP và port → L4, nhanh, mù nội dung.
- Đọc được URL, header, cookie → L7, chậm hơn, nhưng định tuyến theo nghiệp vụ được.
Trong hệ thống lớn, hai tầng này thường xếp chồng chứ không thay thế nhau: L4 quyết định "connection này về Proxy nào", L7 quyết định "request này về Service nào".
2.1 Chia tải ở tầng 4 — Kẻ "mù chữ" siêu tốc độ
L4 hoạt động ở tầng Transport (TCP/UDP). Nó giống như một nhân viên điều phối giao thông bận rộn: chỉ nhìn đúng IP và Cổng (Port) rồi vẫy xe đi tiếp. Nó hoàn toàn không thèm đọc xem bên trong gói tin chứa nội dung gì.
Nghe có vẻ ngốc nghếch, nhưng sự "mù tịt" đó tạo ra tốc độ kinh hoàng. Vì không mất thời gian mở gói tin ra đọc, L4 tốn cực ít CPU và gánh được hàng triệu kết nối cùng lúc. Bạn bắt buộc phải dùng L4 khi:
- Giao thức không phải HTTP: SSH, SMTP, Redis (RESP), game server dùng UDP.
- TLS passthrough: khi backend cần tự xác thực client certificate (mTLS), proxy không được phép giải mã ở giữa.
- Tầng ngoài cùng của hệ thống lớn: L4 hứng toàn bộ traffic vào rồi phân phối cho cụm L7 phía sau.
2.2 Chia tải ở tầng 7 — Bộ não định tuyến thông minh
L7 hoạt động ở tầng Application (HTTP/HTTPS). Trái với L4, nó mở tung gói tin ra để đọc. Nó có thể nhìn vào URL Path, HTTP Headers và Cookies để định tuyến thông minh..
Ví dụ kinh điển là chia route theo URL:
- Khách vào
/api/users/*➔ Mời sang cụm User Server. - Khách vào
/api/orders/*➔ Mời sang cụm Order Server. - Khách vào
/static/*➔ Chuyển luôn thẳng ra CDN.
Cái giá phải trả không nằm ở phép giải mã — như đã nói ở Phần 1, symmetric decryption với AES-NI khá rẻ. Chi phí thật của L7 là: phải parse toàn bộ cú pháp HTTP, phải buffer request body trước khi định tuyến, và phải giữ state cho từng request thay vì từng connection. Cộng thêm việc L7 buộc phải terminate connection nên gánh trọn TLS handshake, trong khi L4 passthrough thì không.
2.3 Chia request cho ai? (Thuật toán điều phối)
Chọn được tầng rồi, câu hỏi tiếp theo là: trong cụm server phía sau, request này nên đi về máy nào? Có ba nhóm thuật toán.
- Static (Tĩnh) — Round Robin. Chia request tuần tự theo vòng lặp: máy 1, máy 2, máy 3, rồi quay lại máy 1. Ưu điểm là cực kỳ dễ triển khai. Nhược điểm là nó chia đều một cách máy móc, nên vẫn có thể gây quá tải nếu không giám sát tốt — chẳng hạn khi một máy nhận toàn request nặng còn máy khác toàn request nhẹ.
- Dynamic (Động) — Least Connections. Ưu tiên đẩy request về server đang có ít kết nối mở nhất. Vì nhìn vào tình trạng thực tế của từng máy tại thời điểm đó, cách chia này sát với công suất thực tế hơn nhiều. Nhưng nó cũng có tử huyệt riêng: một server đang lỗi và trả 500 tức thì sẽ đóng connection rất nhanh, nên trông như đang rảnh nhất và bị dồn thêm traffic. Con máy hỏng nhất lại hút nhiều request nhất. Vì vậy Least Connections luôn phải đi kèm health check để loại máy hỏng ra khỏi pool, chứ không dùng một mình.
- Hash-based —
hash(source_IP) % Nhoặchash(session_id) % N. Dùng khi cần sticky session: cùng một user phải luôn về đúng một máy, chẳng hạn khi session được lưu in-memory. Ưu điểm là không cần lưu bảng ánh xạ ở đâu cả, cứ tính là ra.
Nhóm thứ ba này có một tử huyệt chết người nằm ngay trong công thức của nó. Chúng ta sẽ gặp lại nó ở Phần 4.
Phần 3. Khi hệ thống thành Microservices — API Gateway vào cuộc
Khi hệ thống lớn lên và chia nhỏ thành nhiều Microservices (Backend 1 lo user, Backend 2 lo thanh toán...), nếu Client gọi trực tiếp từng backend thì sẽ cực kỳ hỗn loạn, khó bảo mật và khó quản lý. Ta cần một "người gác cổng" đứng ra hứng mọi đạn pháo và phân loại
API Gateway sinh ra để giải quyết chuyện đó. Hãy hình dung nó như một lễ tân thông minh của tòa nhà: khách chỉ cần đến quầy lễ tân, không cần biết phòng ban nào nằm ở tầng mấy.
API Gateway làm gì?
1. Single Point of Entry. Nó là điểm truy cập duy nhất cho Client, giúp che giấu toàn bộ cấu trúc mạng phức tạp của các dịch vụ backend. Bạn tách service, gộp service, đổi địa chỉ — client không hề hay biết.
2. Authentication & Rate Limiting. Nó thực hiện xác thực tập trung, và kiểm tra giới hạn số request theo IP và Session để chống DDoS. Thay vì mỗi service tự viết logic auth, tất cả gom về một chỗ.
3. Protocol Translation. Nó chuyển đổi giao thức giữa hai thế giới: nhận HTTP/REST từ client (thứ trình duyệt nói được) và dịch sang gRPC để giao tiếp với backend (thứ nhanh hơn cho internal service).
4. Circuit Breaking. Đây là tính năng cứu mạng hệ thống. Khi một backend bắt đầu lỗi, Gateway sẽ ngắt mạch tự động, ngừng gửi request tới nó. Nhờ vậy một service chết không kéo sập cả hệ thống theo hiệu ứng dây chuyền.
Vậy API Gateway khác gì Load Balancer?
Cả hai đều đứng trước backend và đều nhận request, nhưng mục đích khác hẳn:
| Load Balancer | API Gateway | |
|---|---|---|
| Câu hỏi nó trả lời | "Gửi request này về máy nào?" | "Request này được phép làm gì, và đi tới service nào?" |
| Mối quan tâm | Phân bổ tải, tính sẵn sàng | Xác thực, rate limit, đổi giao thức, chống lỗi lan |
| Nhìn thấy | Server trong một cụm | Toàn bộ bản đồ microservices |
Nói ngắn gọn: Load Balancer lo tải, API Gateway lo luật và định tuyến nghiệp vụ. Trong thực tế chúng thường đứng cạnh nhau, không thay thế nhau.
Phần 4. Consistent Hashing — Chia dữ liệu
Bạn biết cách chia traffic rồi, giờ tới bài toán đau đầu hơn: Chia dữ liệu.
Giả sử bạn có 4 con server Cache. Khi một request xin dữ liệu tới, làm sao biết dữ liệu đó đang nằm ở con số mấy?
Cách "ngây thơ" nhất là chia lấy dư (Simple Hashing): vị_trí = hash(key) % 4.
Chạy rất ngon! Cho đến một ngày hệ thống quá tải, bạn cắm thêm con server thứ 5. Mẫu số chia đổi từ 4 thành 5. Bùm! 80% dữ liệu bị tính sai vị trí. Cache miss hàng loạt, Database bị dội bão request và hệ thống của bạn chìm trong biển lửa.
Vòng tròn băm (Consistent Hashing) sinh ra để vá lỗi này.
Thay vì chia lấy dư, người ta bẻ một trục đường thẳng thành một vòng tròn (Hash ring). Sau đó, họ ném cả IP của Server lẫn Dữ liệu (Key) lên cái vòng tròn đó.
Quy tắc tìm đồ cực kỳ thông minh:
- Đứng từ vị trí của Dữ liệu (Key) trên vòng tròn.
- Cứ đi bộ theo chiều kim đồng hồ.
- Vấp phải con Server nào đầu tiên — thì dữ liệu nằm ở đó!
Cái đỉnh cao của Consistent Hashing là gì? Khi bạn thêm hoặc rút một Server, chỉ những dữ liệu nằm trong cung tròn của nó bị ảnh hưởng. Cụ thể, thêm 1 node vào N node có sẵn thì chỉ khoảng 1/(N+1) dữ liệu phải chuyển nhà:
| Từ 4 → 5 server | Simple Hashing (% N) | Consistent Hashing |
|---|---|---|
| Dữ liệu phải di chuyển | 80% | 20% |
| Công thức tổng quát | 1 − 1/(N+1) | 1/(N+1) |
| Từ 100 → 101 server | ~99% | ~1% |
Nhưng vòng tròn thuần có một lỗ hổng chết người. Khi một server chết (khác với việc bạn chủ động thêm vào), toàn bộ cung tròn của nó dồn hết sang đúng một hàng xóm kế tiếp theo chiều kim đồng hồ. Hàng xóm đó vừa gánh phần mình vừa gánh phần người chết → nó cũng gục → lại dồn tiếp sang người thứ ba. Đây là cascading failure.
Virtual Nodes chính là lời giải cho lỗi này — không phải một "mẹo nhỏ" cho đẹp. Mỗi server vật lý được nhân bản thành hàng trăm vị trí ảo rải khắp vòng tròn. Nhờ vậy khi một node chết, tải của nó được rải đều ra tất cả node còn lại thay vì dồn vào một máy duy nhất.
Bản Đồ Ghi Nhớ (Cheat Sheet)
| Trạm trung chuyển | Xử lý nỗi đau gì? | Vị trí đứng |
|---|---|---|
| Forward Proxy | Làm sao ẩn danh và kiểm soát traffic từ Client? | Trước Client |
| Reverse Proxy | Làm sao che giấu và bảo vệ Server? | Trước cụm Server |
| L4 Load Balancer | Làm sao chia tải nhanh, đơn giản và hiệu năng cao? | Trước Database / Queue / Backend |
| L7 Load Balancer | Làm sao chia tải thông minh theo URL, Cookie, Header...? | Trước Web API |
| API Gateway | Làm sao quản lý và kiểm soát hàng trăm Microservices? | Trước toàn bộ Microservices |
| Consistent Hashing | Làm sao thêm/bớt Server mà hạn chế xáo trộn Cache? | Bên trong kiến trúc Caching / Distributed System |
Và mạch logic xuyên suốt: giấu và trung chuyển (Proxy) → chia tải (Load Balancer) → quản lý luật chơi (API Gateway) → chia dữ liệu (Consistent Hashing).
Bạn không cần triển khai cả bốn thứ ngay từ đầu. Thực tế trên cloud, một dòng Terraform tạo ALB đã có sẵn Reverse Proxy, L7 Load Balancer, TLS Termination và Health Check — tất cả nằm trong một “hộp đen”.
Vì vậy, điều quan trọng không phải là tự xây lại chúng, mà là hiểu hộp đen đang làm gì để biết phải nhìn vào đâu khi có sự cố.