TungDaDev's Blog

kiến trúc API Gateway

Api gateway.webp
Published on
/11 mins read/

Trong kiến trúc Microservices, nếu bạn cho phép ứng dụng di động hay trình duyệt web gọi trực tiếp tới hàng chục service nội bộ, bạn đã tự biến hệ thống của mình thành một 'vụ nổ liên lạc' (Communication Explosion): Client phải chịu độ trễ phân tán (Fan-out latency), toàn bộ cấu trúc mạng nội bộ bị phơi bày ra Internet, và việc thay đổi protocol giữa các team trở thành bất khả thi. API Gateway không đơn giản là một Reverse Proxy — nó là 'Bộ Não Điều Phối Lưu Lượng' (Traffic Brain) bảo đảm an ninh, độ tin cậy và hiệu năng cho toàn bộ doanh nghiệp.

Khi một hệ thống phân tán tăng trưởng từ vài services lên hàng chục hoặc hàng trăm services, API Gateway là thành phần sống còn quyết định sự thành bại của kiến trúc. Tuy nhiên, việc lựa chọn công nghệ và thiết kế Gateway sai lầm có thể biến nó thành Điểm nghẽn duy nhất (Single Point of Failure - SPOF) và nút thắt cổ chai về độ trễ (Latency Bottleneck) của toàn bộ hệ sinh thái.

Bài viết này phân tích sâu bản chất kiến trúc của API Gateway, đặt lên bàn cân 3 giải pháp hàng đầu hiện nay: Spring Cloud Gateway vs Kong vs Envoy, đồng thời cung cấp bản thiết kế Distributed Rate Limiting & Circuit Breaker chuẩn production.


# sự tiến hóa kiến trúc: direct access vs API gateway vs bff (backend-for-frontend)

# tại sao mô hình backend-for-frontend (bff) lại lên ngôi?

Một ứng dụng di động (Mobile App) trên sóng 4G/5G có đặc thù rất khác với ứng dụng Web trên đường truyền cáp quang:

  • Mobile App: Cần payload JSON cực kỳ tinh gọn, gộp 5 API thành 1 API call duy nhất (Aggregated Endpoint) để tiết kiệm pin và băng thông.
  • Desktop Web: Cần dữ liệu giàu chi tiết (Rich Data) và có thể tận dụng HTTP/2 đa luồng để tải song song.
  • Public Partner API: Đòi hỏi chuẩn bảo mật nghiêm ngặt OAuth2 Client Credentials và Rate Limiting khắt khe theo hợp đồng thương mại.

→ Giải pháp của Solution Architect: Xây dựng một tầng Edge Gateway chung (chuyên trách SSL Termination, DDoS Protection, WAF) và phân nhánh bên trong thành các BFF Gateways độc lập cho từng trải nghiệm người dùng.


# ma trận đánh đổi 3 chiều: Spring cloud gateway vs kong vs envoy

Không có công nghệ nào là "tốt nhất" cho mọi bài toán. Dưới đây là phân tích kỹ thuật chuyên sâu giữa 3 giải pháp Gateway phổ biến nhất thế giới:

# bảng so sánh chi tiết kỹ thuật

Tiêu chí Đánh giáSpring Cloud Gateway (v4+)Kong Gateway (v3+)Envoy Proxy
Ngôn ngữ & RuntimeJava / Netty (Non-blocking I/O)C / OpenResty (NGINX + LuaJIT)C++ Native
Mức tiêu thụ MemoryTrung bình (~200MB - 512MB Heap)Cực thấp (~30MB - 60MB RAM)Rất thấp (~40MB - 80MB RAM)
P99 Latency Overhead~2ms - 5ms< 1ms< 0.5ms
Cơ chế nạp cấu hìnhStatic YAML hoặc RouteLocator Java BeanDynamic DB-less (YAML) hoặc PostgreSQL ClusterDynamic xDS API (gRPC stream không cần restart)
Khả năng mở rộng PluginViết bằng Java code quen thuộc với toàn bộ Spring DevelopersViết bằng Lua, Go, Python hoặc WebAssembly (Wasm)Viết bằng C++ Filter hoặc WebAssembly (Wasm)
Hệ sinh thái phù hợpCác doanh nghiệp có nền tảng Java / Spring Boot áp đảoDoanh nghiệp đa ngôn ngữ (Polyglot), cần API MarketplaceCloud-Native, Kubernetes Service Mesh, gRPC Streaming

# cơ chế bất đồng bộ: tại sao non-blocking eventloop lại chiến thắng?

Trong quá khứ, Netflix Zuul 1.x từng là biểu tượng của Gateway trong hệ sinh thái Spring. Nhưng Zuul 1.x đã bị đào thải vì mô hình Thread-Per-Request (Blocking I/O):

Spring Cloud Gateway được xây dựng trên nền tảng Project Reactor và Netty:

  • Không cấp phát một luồng hệ điều hành riêng cho mỗi kết nối HTTP.
  • Một số lượng nhỏ các EventLoop Threads (thường bằng 2x số CPU Cores) có thể duy trì và xử lý đồng thời hàng chục nghìn kết nối socket (Concurrent Persistent Connections) với chi phí RAM cực kỳ khiêm tốn.

# kiểm soát lưu lượng: thuật toán distributed token bucket với Redis lua

Trong môi trường phân tán gồm nhiều Pod Gateway chạy song song phía sau Load Balancer, giải pháp Rate Limiting cục bộ trên RAM của từng Pod sẽ hoàn toàn phá sản. Chúng ta bắt buộc phải sử dụng Distributed Rate Limiting.

# tại sao bắt buộc phải dùng Redis lua script?

Nếu tách rời thành 2 lệnh:

  1. redis.get(key) để kiểm tra số token còn lại.
  2. redis.decr(key) để trừ token. Giữa 2 lệnh này sẽ xảy ra Race Condition khủng khiếp khi có hàng ngàn requests dồn tới trong cùng một mili-giây. Lua Script trong Redis đảm bảo tính nguyên tử (Atomicity 100%): Toàn bộ thuật toán hồi token và trừ token được thực thi trong một chu kỳ CPU duy nhất của Redis engine.

# khả năng tự phục hồi: distributed circuit breaker & fallback

Một Gateway cấp doanh nghiệp phải có khả năng bảo vệ hệ thống khỏi Lỗi dây chuyền (Cascading Failure). Khi một microservice phía sau bị chậm hoặc sập hoàn toàn, Gateway phải ngắt mạch ngay lập tức và trả về dữ liệu dự phòng (Fallback):


# blueprint triển khai production với Spring cloud gateway

Dưới đây là manifest cấu hình Spring Boot 3.4+ hoàn chỉnh, tích hợp Token Relay (OAuth2/JWT), Redis Rate Limiting, và Resilience4j Circuit Breaker:

spring:
  cloud:
    gateway:
      default-filters:
        # Bóc tách và chuyển tiếp W3C TraceContext cho OpenTelemetry
        - RemoveRequestHeader=Cookie
        - AddRequestHeader=X-Gateway-Processed, true
      routes:
        # Route 1: Order Service với Rate Limiting & Circuit Breaker
        - id: order-service-route
          uri: lb://order-service # Cân bằng tải nội bộ qua Spring Cloud LoadBalancer
          predicates:
            - Path=/api/v1/orders/**
            - Method=GET,POST,PUT,DELETE
          filters:
            # Gắn Circuit Breaker: Khi lỗi chuyển về /fallback/orders
            - name: CircuitBreaker
              args:
                name: orderServiceCircuitBreaker
                fallbackUri: forward:/fallback/orders
            # Gắn Distributed Rate Limiter dùng Redis
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 100 # Tốc độ hồi phục: 100 tokens/giây
                redis-rate-limiter.burstCapacity: 200 # Dung lượng tối đa: Chịu đỉnh 200 requests/giây
                redis-rate-limiter.requestedTokens: 1
                key-resolver: '#{@userKeyResolver}' # Phân loại rate limit theo JWT User ID hoặc IP
            # Chuyển tiếp JWT Token xuống Microservice phía dưới
            - TokenRelay=
 
resilience4j:
  circuitbreaker:
    instances:
      orderServiceCircuitBreaker:
        slidingWindowType: COUNT_BASED
        slidingWindowSize: 20
        failureRateThreshold: 50
        waitDurationInOpenState: 10000ms
        permittedNumberOfCallsInHalfOpenState: 5

Định nghĩa Key Resolver theo ngữ cảnh định danh người dùng:

@Configuration
public class RateLimiterConfiguration {
 
    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> {
            // Ưu tiên 1: Rate limit theo User ID trích xuất từ JWT Token
            return exchange.getPrincipal()
                .map(Principal::getName)
                // Ưu tiên 2 (Khách vãng lai): Fallback về địa chỉ IP thực tế (xử lý qua X-Forwarded-For)
                .switchIfEmpty(Mono.just(
                    Optional.ofNullable(exchange.getRequest().getHeaders().getFirst("X-Forwarded-For"))
                        .orElse(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress())
                ));
        };
    }
}

# bảng kiểm tra sẵn sàng vận hành (architect's checklist)

  • 1. High Availability (Không Điểm Nghẽn SPOF): Cụm Gateway có tối thiểu từ 3 pods trở lên, được phân bổ đều trên các Availability Zones khác nhau phía sau Cloud Load Balancer (AWS ALB / GCP GLB) không?
  • 2. Throttling & DDoS Defense: Đã cài đặt Rate Limiting theo cả 2 tầng: Tầng IP (ngăn chặn brute-force/DDoS) và Tầng User ID / API Key (bảo vệ quota nghiệp vụ) chưa?
  • 3. Timeout Tuyệt Đối: Mọi route qua Gateway đều bắt buộc phải cấu hình response-timeout và connect-timeout (khuyến nghị 3.000ms - 5.000ms) để chống cạn kiệt socket.
  • 4. Protocol Translation: Đã tận dụng Gateway để chuyển tiếp từ HTTP/1.1 (từ Client ngoài Internet) sang gRPC / HTTP/2 (giữa các microservices nội bộ) để tối ưu băng thông chưa?
  • 5. Distributed Tracing Injection: Gateway có tự động sinh X-Correlation-Id và chèn W3C traceparent headers trước khi đẩy request vào mạng nội bộ không?

# lời kết

API Gateway là trái tim điều phối của toàn bộ hệ sinh thái Microservices. Một kiến trúc Gateway xuất sắc không chỉ đứng ra gánh vác các bài toán phụ trợ dùng chung (Cross-Cutting Concerns) như Security, Rate Limiting, Caching hay Tracing, mà còn mang lại sự độc lập tuyệt đối cho các nhóm phát triển dịch vụ phía sau.

Nắm vững cơ chế vận hành bất đồng bộ, hiểu rõ điểm mạnh yếu của từng giải pháp (Spring Cloud Gateway, Kong, Envoy) và làm chủ các mô hình phân tán (BFF, Circuit Breaker) chính là vũ khí tối thượng của một Solution Architect trên hành trình xây dựng các hệ thống có khả năng chịu tải hàng trăm triệu lượt truy vấn mỗi ngày.


Chỉ là những ghi chép cá nhân với hy vọng mang lại chút giá trị. Nếu thấy hữu ích, đừng ngại chia sẻ cho bạn bè & đồng nghiệp nhé!

Happy coding 😎 👍🏻 🚀 🔥.

← Previous postredis pattern