API gateway pattern

API Gateway

Là một thành phần trung gian đứng giữa client và các microservices, đóng vai trò như một cổng truy cập duy nhất cho tất cả các request từ bên ngoài vào hệ thống. API Gateway giúp quản lý request, thực hiện load balancing, bảo mật, logging, caching, và điều phối luồng dữ liệu giữa client và backend services.

Tại sao cần API Gateway trong Microservices?

Khi ứng dụng microservices phát triển, nếu client gọi trực tiếp từng service, sẽ có những vấn đề sau:

  1. Client phải biết chi tiết từng service

    • Khi hệ thống có nhiều service, client cần biết địa chỉ từng service để gọi API.

    • Nếu một service đổi URL hoặc bị thay thế, client cũng phải thay đổi theo.

  2. Quá nhiều request từ client

    • Một trang web hoặc ứng dụng mobile có thể cần dữ liệu từ nhiều service.

    • Client phải gửi nhiều request → Tăng thời gian phản hồi (latency) và giảm hiệu suất.

  3. Quản lý bảo mật khó khăn

    • Mỗi service phải tự xử lý authentication, authorization, logging, rate-limiting.

    • Dễ dẫn đến lỗi bảo mật nếu không đồng nhất.

Giải pháp: Dùng API Gateway để làm lớp trung gian giữa client và backend

Cơ chế hoạt động của API Gateway

  1. Nhận request từ client: Tất cả request từ client (web, mobile, API khác) đều đi qua API Gateway.

  2. Routing request: API Gateway xác định request cần chuyển đến microservice nào.

  3. Xử lý trước request (Pre-processing): Kiểm tra xác thực (authentication), ủy quyền (authorization), log dữ liệu, caching, v.v.

  4. Gửi request đến microservices: Sau khi xác thực, API Gateway gửi request đến microservice phù hợp.

  5. Nhận phản hồi từ microservices: API Gateway gom dữ liệu từ nhiều microservices (nếu cần), xử lý dữ liệu, và gửi phản hồi về client.

  6. Trả kết quả về client: API Gateway có thể nén dữ liệu, caching kết quả, hoặc thay đổi response format trước khi gửi về client.

Trường hợp sử dụng API Gateway

  • Tập trung hóa điểm truy cập: Thay vì mỗi client phải gọi nhiều microservices riêng lẻ, API Gateway giúp tập trung tất cả vào một đầu mối duy nhất.

  • Load Balancing: API Gateway có thể phân phối request đến các instance khác nhau của cùng một microservice.

  • Bảo mật: Kiểm tra xác thực (JWT, OAuth, API Key) và ủy quyền trước khi cho phép truy cập.

  • CORS & Rate Limiting: Hạn chế số request từ client hoặc chặn truy cập không mong muốn.

  • Aggregation (Tổng hợp dữ liệu): Khi một trang web/mobile app cần dữ liệu từ nhiều service, API Gateway có thể tổng hợp dữ liệu từ nhiều microservices rồi trả về một response duy nhất.

  • Caching: Giảm tải hệ thống bằng cách cache response từ các microservices phổ biến.

Ví dụ:

  • Ứng dụng thương mại điện tử: API Gateway tổng hợp dữ liệu từ các microservices như giỏ hàng, danh sách sản phẩm, đơn hàng.

  • Hệ thống tài chính: API Gateway giúp bảo vệ các API thanh toán với cơ chế xác thực chặt chẽ.

  • Cần kiểm soát request từ client (rate limiting, CORS).

Không cần API Gateway nếu:

  • Hệ thống chỉ có 1-2 service và không có nhu cầu bảo mật/caching phức tạp.

Các cách triển khai

1. Sử dụng API Gateway có sẵn

Một số giải pháp API Gateway phổ biến:

  • Kong Gateway - Mạnh mẽ, hỗ trợ plugin linh hoạt.

  • NGINX API Gateway - Nhẹ, hiệu suất cao.

  • AWS API Gateway - Tích hợp tốt với AWS Lambda, EC2, S3.

  • Traefik - Hỗ trợ dynamic routing cho Kubernetes.

  • Istio (Service Mesh) - Tích hợp API Gateway với kiến trúc service mesh.

2. Tự xây dựng API Gateway với Spring Cloud Gateway

Cài đặt Spring Cloud Gateway trong pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

Cấu hình API Gateway trong application.yml:


spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/users/**
        - id: order-service
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/orders/**

Controller để kiểm tra API Gateway:

@RestController
@RequestMapping("/fallback")
public class FallbackController {
    @GetMapping("/user")
    public ResponseEntity<String> userServiceFallback() {
        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
                             .body("User Service is down!");
    }
}