Software Architecture

API Gateway & Service Mesh: Kiến trúc mạng và sự trừu tượng hóa hạ tầng

7/19/2026 · 13p đọc


title: "API Gateway & Service Mesh: Kiến trúc mạng và sự trừu tượng hóa hạ tầng"
series: "Software Architecture Masterclass"
part: "Phần 2 — Cấu trúc & Patterns"
order: 20
audience: "Solutions Architect & Technical Lead"
reading_time: "14 phút"
tags:

  • "software-architecture"
  • "api-gateway"
  • "service-mesh"
  • "sidecar"
  • "mtls"
  • "observability"
  • "microservices"

API Gateway & Service Mesh: Kiến trúc mạng và sự trừu tượng hóa hạ tầng

Một tổ chức có 25 microservices. Mỗi service tự viết logic xác thực JWT. Mỗi service tự implement retry với exponential backoff — một số làm đúng, một số retry vô hạn và khuếch đại sự cố downstream thành cascading failure. Mỗi service tự quyết định timeout, một số để mặc định của thư viện HTTP client (có khi là 0, tức là vô hạn). Rate limiting tồn tại ở ba service, không tồn tại ở hai mươi hai service còn lại. TLS giữa các service nội bộ — có team bật, có team tắt vì "trong VPC rồi, an toàn".

Đây không phải kịch bản giả định để minh họa lý thuyết. Đây là hình dạng thật của phần lớn hệ thống microservices sau 18-24 tháng tăng trưởng hữu cơ, khi mỗi team được trao quyền tự trị (autonomy) nhưng không ai được giao trách nhiệm cho các mối quan tâm xuyên suốt (cross-cutting concerns). Kết quả không phải là 25 service độc lập vận hành tốt — mà là 25 cách hiện thực hóa không nhất quán cho cùng một tập vấn đề hạ tầng.

Bài này giải quyết câu hỏi: những mối quan tâm nào nên được kéo ra khỏi từng service và tập trung hóa ở đâu trong topology mạng, và cái giá phải trả cho việc tập trung hóa đó là gì. Đây cũng là bài chốt Phần 2 của series — vì API Gateway và Service Mesh chính là lớp hạ tầng nối liền mọi pattern cấu trúc (Hexagonal, CQRS, SAGA, Event-Driven) đã bàn ở các bài trước vào một hệ thống vận hành được ở quy mô thật.

The Problem

Tách vấn đề thành hai lớp giao tiếp khác nhau về bản chất, thường bị gộp chung một cách sai lầm:

Lớp 1 — Traffic từ bên ngoài vào (north-south traffic). Client (web, mobile, đối tác thứ ba) gọi vào hệ thống. Câu hỏi: request này đi vào service nào, ai được phép gọi, gọi bao nhiêu lần một phút, dùng version API nào. Nếu không tập trung hóa, mỗi service tự expose endpoint ra internet, tự viết logic auth, tự set rate limit — nghĩa là 25 bề mặt tấn công (attack surface) khác nhau, 25 chính sách bảo mật khác nhau, và một API consumer bên ngoài phải biết chi tiết nội bộ (địa chỉ, port, giao thức) của từng service để gọi đúng.

Lớp 2 — Traffic giữa các service nội bộ (east-west traffic). Service A gọi service B gọi service C. Câu hỏi: kết nối này có được mã hóa không, nếu B tạm thời chậm thì A có retry hợp lý không, nếu C liên tục lỗi thì có ai ngắt mạch (circuit breaker) để tránh khuếch đại sự cố không, và khi debug một request đi qua 5 service, ai cho ta bức tranh toàn cảnh về latency ở từng chặng.

Vấn đề kiến trúc cốt lõi: cả hai lớp này đều là mối quan tâm hạ tầng thuần túy (infrastructure concern), không phải business logic — nhưng khi không có nơi nào chịu trách nhiệm tập trung, chúng bị lẫn vào code nghiệp vụ của từng service, được implement lại N lần với N chất lượng khác nhau, và không ai có khả năng thay đổi chính sách toàn cục (ví dụ: bắt buộc mTLS cho mọi service nội bộ) mà không sửa từng service một.

Sai lầm thường gặp là dùng một công cụ cho cả hai lớp — ví dụ nhét toàn bộ logic retry/circuit-breaking vào API Gateway ở biên, hoặc expose service mesh sidecar trực tiếp ra internet. Hai lớp này có mô hình đe dọa (threat model), yêu cầu độ trễ, và tần suất thay đổi khác nhau — gộp chung tạo ra một thành phần vừa quá tải trách nhiệm vừa là điểm chịu rủi ro kép.

The Theory

API Gateway — cửa ngõ cho traffic bên ngoài

API Gateway là một reverse proxy có state về nghiệp vụ API, đứng ở biên (edge) của hệ thống, chịu trách nhiệm cho mọi request đi từ bên ngoài vào:

  • Routing: ánh xạ một endpoint công khai (/api/v1/orders) tới đúng service nội bộ, ẩn hoàn toàn cấu trúc nội bộ khỏi consumer bên ngoài.
  • Authentication & Authorization: xác thực token (JWT, API key, OAuth2) một lần tại cửa, thay vì mỗi service tự verify.
  • Rate limiting & throttling: áp policy theo consumer, theo endpoint, đôi khi theo gói dịch vụ (tier) khách hàng đã trả tiền.
  • Request/response transformation: gộp nhiều service thành một API hợp nhất cho client (API composition), hoặc biến đổi định dạng cho từng loại consumer (mobile cần payload nhẹ hơn web).
  • TLS termination: giải mã HTTPS một lần tại biên.

Về bản chất, API Gateway là điểm tập trung hóa hợp đồng với thế giới bên ngoài — nó biến "N service, N cách gọi" thành "một bề mặt API nhất quán".

Service Mesh — hạ tầng giao tiếp cho traffic nội bộ

Service Mesh giải quyết vấn đề khác: khi số lượng service nội bộ đủ lớn, làm sao đảm bảo mọi kết nối service-to-service đều tuân theo cùng một chính sách bảo mật và độ tin cậy mà không cần sửa code từng service.

Cơ chế: một tiến trình proxy nhẹ (sidecar) được triển khai cạnh mỗi instance service (thường trong cùng pod, ví dụ mô hình sidecar của Envoy proxy trong hệ sinh thái Kubernetes). Mọi traffic ra/vào service đều đi qua sidecar của nó trước, thay vì gọi trực tiếp network. Tập hợp các sidecar tạo thành data plane; một control plane trung tâm cấu hình và điều phối toàn bộ sidecar (chính sách routing, mTLS certificate, luật retry).

Service mesh cung cấp:

  • mTLS tự động giữa mọi service, không cần service tự implement TLS handshake.
  • Retry, timeout, circuit breaking cấu hình tập trung ở control plane, áp dụng thống nhất, không phụ thuộc vào việc từng team có nhớ implement đúng hay không.
  • Traffic shaping: canary release, traffic splitting theo phần trăm, fault injection để kiểm thử khả năng chịu lỗi.
  • Observability đồng nhất: mọi sidecar phát ra metric/trace theo cùng format, cho bức tranh toàn cảnh latency từng hop mà không cần mỗi service tự đo.

Điểm mấu chốt về triết lý: cả hai pattern đều dựa trên nguyên tắc tách mối quan tâm hạ tầng ra khỏi code nghiệp vụ và đẩy nó xuống một tầng hạ tầng dùng chung — API Gateway làm điều này cho biên ngoài, Service Mesh làm điều này cho lưới nội bộ. Chúng không cạnh tranh nhau — một hệ thống trưởng thành thường có cả hai, mỗi cái phục vụ đúng lớp giao tiếp của mình.

The Trade-off

Không có mối quan tâm xuyên suốt nào được tập trung hóa miễn phí — bạn đang đổi sự trùng lặp phân tán lấy một điểm phụ thuộc mới.

Chọn API Gateway

Được gì:

  • Một điểm duy nhất áp policy auth/rate-limit/TLS cho toàn bộ traffic bên ngoài — sửa chính sách một chỗ, có hiệu lực với mọi consumer.
  • Ẩn cấu trúc nội bộ khỏi client: đổi service nội bộ, tách/gộp service, đổi giao thức nội bộ (REST sang gRPC) — client bên ngoài không hay biết vì hợp đồng công khai không đổi.
  • Giảm attack surface: chỉ một điểm expose ra internet cần audit bảo mật kỹ, thay vì 25 điểm.
  • API composition cho phép client nhận một response tổng hợp thay vì tự gọi nhiều service rồi tự ráp — giảm số round-trip từ phía client.

Mất gì:

  • Gateway trở thành thành phần hạ tầng trọng yếu (critical infrastructure component) — nếu nó down, toàn bộ traffic bên ngoài ngừng, kể cả khi mọi service nội bộ vẫn khỏe mạnh hoàn toàn. Yêu cầu độ sẵn sàng cao (multi-AZ, không có single point of failure ở chính gateway) không phải tùy chọn, mà là bắt buộc — và tự nó là một hệ thống cần vận hành, giám sát, và có runbook riêng.
  • Thêm một hop mạng cho mọi request — latency cộng dồn, dù thường nhỏ (single-digit millisecond) nhưng không phải bằng không, và cộng dồn có ý nghĩa với hệ thống nhạy cảm độ trễ (trading, real-time bidding).
  • Rủi ro lớn nhất, hay bị đánh giá thấp: gateway dễ trở thành nơi chứa business logic "tạm" — một rule composition phức tạp, một transform đặc thù cho một khách hàng lớn — rồi ở lại vĩnh viễn, biến gateway thành một monolith ẩn giống hệt bài học ESB đã nêu ở phần SOA (Bài 15). Team sở hữu gateway trở thành bottleneck tổ chức: mọi thay đổi routing phải qua họ.
  • Versioning và thay đổi cấu hình gateway cần quy trình review riêng vì tác động toàn hệ thống — không thể để một team tự ý sửa route ảnh hưởng service khác.

Chọn Service Mesh

Được gì:

  • mTLS, retry, circuit breaking được đảm bảo nhất quán cho mọi service, không phụ thuộc vào việc từng đội có implement đúng — loại bỏ hoàn toàn lớp bug "team quên set timeout" đã mô tả ở phần Problem.
  • Observability đồng nhất theo mọi hop mà không cần sửa code service để thêm instrumentation — sidecar tự động sinh metric/trace.
  • Traffic shaping (canary, A/B, fault injection) thực hiện ở tầng hạ tầng, tách khỏi vòng đời deploy của service — team vận hành có thể test khả năng chịu lỗi mà không cần mỗi service tự cài đặt logic đó.
  • Chính sách bảo mật nội bộ (zero-trust giữa các service) áp dụng tập trung, sửa một chỗ có hiệu lực toàn lưới.

Mất gì:

  • Chi phí tài nguyên sidecar nhân với số lượng instance: mỗi pod/instance service giờ chạy thêm một proxy — với hệ thống có hàng trăm instance, tổng CPU/memory dành cho sidecar có thể là một khoản chi phí hạ tầng đáng kể, không phải chi phí biên nhỏ.
  • Độ trễ mỗi hop tăng gấp đôi thực chất: traffic từ A đến B giờ đi qua sidecar-A rồi mới ra network rồi vào sidecar-B rồi mới tới B — với một request đi qua chuỗi 5-6 service, độ trễ cộng dồn từ sidecar có thể trở thành phần đáng kể của tổng latency, đặc biệt với hệ thống có yêu cầu p99 khắt khe.
  • Độ phức tạp vận hành control plane: control plane của service mesh tự nó là một hệ thống phân tán phức tạp cần vận hành, nâng cấp, và debug khi có sự cố — và khi control plane có vấn đề, việc chẩn đoán "sidecar đang làm gì" khó hơn debug code ứng dụng thông thường vì nó là một tầng network trong suốt (transparent) mà đa số kỹ sư ứng dụng không có kinh nghiệm vận hành.
  • Đường cong học tập cao và rủi ro vận hành khi số service còn ít: với 5-10 service, chi phí vận hành mesh (thêm một control plane, thêm sidecar, thêm một tầng để debug) thường lớn hơn lợi ích nó mang lại so với việc implement retry/circuit-breaker bằng thư viện dùng chung ở tầng ứng dụng.

Nói ngắn gọn: API Gateway mua sự nhất quán ở biên bằng cái giá tạo ra một thành phần hạ tầng trọng yếu mới cần độ sẵn sàng cực cao; Service Mesh mua sự nhất quán ở lưới nội bộ bằng cái giá độ trễ mỗi hop và một control plane phức tạp cần đội vận hành riêng. Cả hai đều là quyết định tập trung hóa — và tập trung hóa luôn đánh đổi tính đơn giản phân tán lấy rủi ro tập trung.

The Architecture Diagram

flowchart TB
    subgraph External["Bên ngoài"]
        WebClient[Web Client]
        MobileClient[Mobile Client]
        Partner[Đối tác API]
    end

    subgraph Edge["Biên hệ thống — North-South Traffic"]
        GW[API Gateway<br/>routing · auth · rate-limit · TLS termination]
    end

    subgraph Mesh["Nội bộ — East-West Traffic qua Service Mesh"]
        direction TB
        subgraph SvcA["Order Service"]
            A[App Container]
            SA[Sidecar Proxy]
            A <--> SA
        end
        subgraph SvcB["Inventory Service"]
            B[App Container]
            SB[Sidecar Proxy]
            B <--> SB
        end
        subgraph SvcC["Payment Service"]
            C[App Container]
            SC[Sidecar Proxy]
            C <--> SC
        end
        CP{{Control Plane<br/>cấu hình mTLS · retry · traffic policy}}
        SA <-.mTLS, retry, circuit-break.-> SB
        SB <-.mTLS, retry, circuit-break.-> SC
        CP -.điều phối.-> SA
        CP -.điều phối.-> SB
        CP -.điều phối.-> SC
    end

    WebClient --> GW
    MobileClient --> GW
    Partner --> GW
    GW -->|route đến service phù hợp| SA

Điểm mấu chốt của topology: API Gateway chỉ xuất hiện một lần, ở biên, xử lý traffic đi vào từ thế giới bên ngoài. Bên trong, mọi giao tiếp service-to-service không đi thẳng qua network mà đi qua cặp sidecar, được điều phối bởi một control plane trung tâm — gateway không biết và không cần biết chuyện gì xảy ra bên trong lưới nội bộ, và sidecar không xử lý traffic từ internet. Hai lớp tách biệt rõ ràng cả về vị trí lẫn trách nhiệm.

Implementation Guardrails

  1. Không đặt business logic trong Gateway. Gateway chỉ làm bốn việc: route, xác thực định danh, áp rate limit, transform định dạng (không transform ngữ nghĩa nghiệp vụ). Bất kỳ quy tắc nào cần biết "đơn hàng này có hợp lệ không", "khách hàng này có được giảm giá không" — phải nằm trong service sở hữu nghiệp vụ đó. Đây là bài học lặp lại từ ESB (Bài 15): công cụ tích hợp phình to thành business logic là con đường chắc chắn dẫn tới monolith ẩn không ai dám sửa.

  2. Chỉ giới thiệu Service Mesh khi độ phức tạp giao tiếp nội bộ đủ lớn để biện minh chi phí vận hành — không phải cho vài service. Ngưỡng thực tế thường nằm ở hàng chục microservices trở lên, khi số lượng kết nối point-to-point và sự không nhất quán trong retry/mTLS đã gây sự cố thật (không phải sự cố giả định). Với dưới 10-15 service, một thư viện dùng chung (shared HTTP client library có sẵn retry/timeout/circuit-breaker) thường đạt phần lớn lợi ích với chi phí vận hành thấp hơn nhiều.

  3. Gateway và Mesh phải có SLA vận hành riêng, cao hơn service nghiệp vụ thông thường, kèm chiến lược high-availability tường minh (multi-instance, multi-AZ, health check tự động failover). Vì đây là hạ tầng dùng chung cho mọi traffic, downtime của nó có bán kính ảnh hưởng (blast radius) lớn hơn downtime của một service đơn lẻ — coi nó như hạ tầng lõi (core infrastructure), không phải một service phụ.

  4. Tách rõ cấu hình chính sách hạ tầng (đặt trong control plane/gateway config) khỏi code service — và bắt buộc mọi thay đổi cấu hình có review, versioning, khả năng rollback nhanh, vì một thay đổi routing hoặc policy sai ảnh hưởng đồng thời nhiều service, khác hẳn một bug trong code service chỉ ảnh hưởng chính nó.

Architect's Verdict

API Gateway hầu như luôn đáng giá ngay khi hệ thống có API consumer bên ngoài — chi phí vận hành một gateway thấp hơn nhiều so với cái giá của 25 bề mặt bảo mật không nhất quán, và lợi ích ẩn cấu trúc nội bộ khỏi client gần như không có nhược điểm thực chất ngoài việc cần đảm bảo độ sẵn sàng cao. Service Mesh thì ngược lại — nó là công cụ trả lời cho một vấn đề chỉ xuất hiện ở quy mô (hàng chục microservices trở lên với giao tiếp nội bộ phức tạp); đưa mesh vào một hệ thống 8 service là nhập khẩu độ phức tạp vận hành mà chưa có vấn đề tương xứng để giải quyết. Luôn hỏi trước: "vấn đề tôi đang cố giải bằng mesh — nó đã thực sự gây sự cố chưa, hay tôi đang phòng ngừa một kịch bản chưa xảy ra?"

🔗 Bài viết liên quan


Bài trước: SAGA Pattern · Bài tiếp theo: CAP Theorem

API Gateway & Service Mesh: Kiến trúc mạng và sự trừu tượng hóa hạ tầng