API Gateway 2026 — Kiến trúc Cổng Trung Tâm cho Microservices với YARP, Kong và BFF Pattern
Posted on: 4/18/2026 10:12:46 AM
Table of contents
- 1. API Gateway là gì và tại sao Microservices cần nó?
- 2. Kiến trúc API Gateway — Các Pattern Thiết Kế
- 3. YARP — API Gateway trên .NET 10
- 4. So sánh các API Gateway phổ biến 2026
- 5. Authentication tại Gateway Layer
- 6. Rate Limiting — Bảo vệ Backend
- 7. Load Balancing và Circuit Breaker
- 8. Backend-for-Frontend (BFF) Pattern — Triển khai thực tế
- 9. Observability — Monitoring API Gateway
- 10. Best Practices cho Production
- 11. Kiến trúc tổng thể — Gateway trong Production Stack
- Kết luận
- Tài liệu tham khảo
Trong kiến trúc microservices, một trong những thách thức lớn nhất là: Client kết nối với bao nhiêu service? Khi hệ thống có 10, 50, hay 200 service, việc để client gọi trực tiếp từng service không chỉ phức tạp mà còn là cơn ác mộng về bảo mật và vận hành. API Gateway chính là lời giải — một cổng trung tâm duy nhất đứng giữa client và toàn bộ backend, xử lý routing, authentication, rate limiting, load balancing và hàng loạt cross-cutting concerns.
Bài viết này sẽ đi sâu vào kiến trúc API Gateway năm 2026, từ các pattern thiết kế cốt lõi, triển khai thực tế với YARP trên .NET 10, so sánh với Kong và AWS API Gateway, đến Backend-for-Frontend (BFF) pattern cho hệ thống production.
1. API Gateway là gì và tại sao Microservices cần nó?
API Gateway là một reverse proxy đứng giữa client (web, mobile, third-party) và các backend services. Thay vì client phải biết địa chỉ và giao thức của từng service, tất cả request đều đi qua một điểm duy nhất — gateway — rồi được route đến đúng service phía sau.
graph TB
subgraph Clients
WEB[Web App]
MOB[Mobile App]
EXT[3rd-party API]
end
GW[API Gateway]
subgraph Backend Services
US[User Service]
OS[Order Service]
PS[Product Service]
NS[Notification Service]
end
WEB --> GW
MOB --> GW
EXT --> GW
GW --> US
GW --> OS
GW --> PS
GW --> NS
style GW fill:#e94560,stroke:#fff,color:#fff
style WEB fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50
style MOB fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50
style EXT fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50
style US fill:#2c3e50,stroke:#fff,color:#fff
style OS fill:#2c3e50,stroke:#fff,color:#fff
style PS fill:#2c3e50,stroke:#fff,color:#fff
style NS fill:#2c3e50,stroke:#fff,color:#fff
Tại sao không gọi trực tiếp từng service?
Khi client gọi trực tiếp: (1) Phải quản lý N endpoint khác nhau, (2) Mỗi service phải tự xử lý auth, rate limiting, CORS, (3) Thay đổi nội bộ (tách/merge service) ảnh hưởng trực tiếp đến client, (4) Không có điểm trung tâm để monitor traffic. API Gateway giải quyết tất cả bằng cách tập trung cross-cutting concerns vào một layer duy nhất.
1.1. Những gì API Gateway xử lý
Routing & Path Rewriting
Map URL public sang internal service endpoints. Ví dụ: /api/orders/* → Orders Service, /api/users/* → User Service. Hỗ trợ path prefix stripping, query string forwarding.
Authentication & Authorization
Validate JWT/OAuth2 token một lần tại gateway, forward claims xuống downstream services. Loại bỏ việc mỗi service phải tự validate token.
Rate Limiting & Throttling
Bảo vệ backend khỏi abuse bằng fixed window, sliding window hoặc token bucket algorithm. Apply theo IP, user, API key hoặc route cụ thể.
Load Balancing
Phân phối traffic qua multiple instances: Round Robin, Least Connections, Weighted, hoặc Consistent Hashing. Kết hợp health checks để loại instance lỗi.
Response Caching
Cache response tại gateway layer cho các endpoint read-heavy, giảm load xuống backend. Hỗ trợ cache invalidation qua header hoặc TTL.
Observability & Logging
Tracing mỗi request từ client đến backend với correlation ID. Export metrics (latency, error rate, throughput) sang Prometheus/OpenTelemetry.
2. Kiến trúc API Gateway — Các Pattern Thiết Kế
2.1. Single Gateway vs Gateway per Client
Có hai cách tiếp cận chính khi thiết kế API Gateway:
graph LR
subgraph "Pattern 1: Single Gateway"
C1[All Clients] --> SG[Shared Gateway]
SG --> S1[Service A]
SG --> S2[Service B]
end
subgraph "Pattern 2: BFF — Gateway per Client"
WA[Web App] --> WG[Web Gateway]
MA[Mobile App] --> MG[Mobile Gateway]
PA[Partner API] --> PG[Partner Gateway]
WG --> S3[Service A]
MG --> S3
PG --> S3
WG --> S4[Service B]
MG --> S4
PG --> S4
end
style SG fill:#e94560,stroke:#fff,color:#fff
style WG fill:#e94560,stroke:#fff,color:#fff
style MG fill:#e94560,stroke:#fff,color:#fff
style PG fill:#e94560,stroke:#fff,color:#fff
style S1 fill:#2c3e50,stroke:#fff,color:#fff
style S2 fill:#2c3e50,stroke:#fff,color:#fff
style S3 fill:#2c3e50,stroke:#fff,color:#fff
style S4 fill:#2c3e50,stroke:#fff,color:#fff
Single Gateway đơn giản, dễ quản lý, phù hợp hệ thống nhỏ-trung. Nhưng khi Web cần response khác Mobile (ít field hơn, format khác), single gateway trở thành bottleneck — mỗi thay đổi cho mobile ảnh hưởng web và ngược lại.
BFF Pattern (Backend-for-Frontend) giải quyết vấn đề này: mỗi loại client có gateway riêng, tùy chỉnh response shape, aggregation logic và caching strategy theo đúng nhu cầu. Netflix, Spotify và Shopify đều sử dụng BFF cho production.
2.2. Request Pipeline trong API Gateway
Một request đi qua gateway sẽ trải qua nhiều middleware layer theo thứ tự cố định. Thứ tự này cực kỳ quan trọng — đặt sai có thể gây lỗ hổng bảo mật hoặc hành vi không mong muốn.
graph TB
REQ[Incoming Request] --> CORS[CORS Middleware]
CORS --> RL[Rate Limiting]
RL --> AUTH[Authentication]
AUTH --> AUTHZ[Authorization]
AUTHZ --> CACHE[Response Cache Check]
CACHE --> TRANSFORM[Request Transform]
TRANSFORM --> ROUTE[Route Matching]
ROUTE --> LB[Load Balancer]
LB --> HEALTH[Health Check Filter]
HEALTH --> PROXY[Proxy to Backend]
PROXY --> RES_TRANSFORM[Response Transform]
RES_TRANSFORM --> LOG[Logging & Metrics]
LOG --> RES[Response to Client]
style REQ fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50
style CORS fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style RL fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style AUTH fill:#e94560,stroke:#fff,color:#fff
style AUTHZ fill:#e94560,stroke:#fff,color:#fff
style CACHE fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style TRANSFORM fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style ROUTE fill:#2c3e50,stroke:#fff,color:#fff
style LB fill:#2c3e50,stroke:#fff,color:#fff
style HEALTH fill:#2c3e50,stroke:#fff,color:#fff
style PROXY fill:#2c3e50,stroke:#fff,color:#fff
style RES_TRANSFORM fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style LOG fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style RES fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50
⚠ Thứ tự middleware quan trọng
Rate Limiting PHẢI trước Authentication. Nếu đặt ngược, attacker có thể spam request với invalid token — gateway vẫn tốn resource để validate JWT trước khi rate limit kick in. Đặt rate limiting trước giúp chặn abuse sớm nhất có thể mà không tốn CPU cho crypto operations.
2.3. Gateway Aggregation Pattern
Một trong những pattern mạnh nhất của API Gateway là request aggregation — gộp nhiều backend calls thành một response duy nhất cho client. Thay vì mobile app gọi 3 API riêng biệt (user profile, orders, recommendations), gateway gọi song song cả 3, merge kết quả và trả về một response.
// Ví dụ aggregation: Client gọi GET /api/dashboard
// Gateway internally gọi song song:
// GET /users/123/profile
// GET /orders?userId=123&limit=5
// GET /recommendations?userId=123
// Merge thành 1 response { profile, recentOrders, recommendations }
Pattern này đặc biệt hữu ích cho mobile app (giảm số lượng HTTP roundtrips trên mạng chậm) và cho trang dashboard (giảm waterfall loading).
3. YARP — API Gateway trên .NET 10
YARP (Yet Another Reverse Proxy) là thư viện mã nguồn mở của Microsoft, được thiết kế như một reverse proxy có thể lập trình hoàn toàn trên ASP.NET Core. Không giống Kong hay AWS API Gateway — là sản phẩm có sẵn feature — YARP là một toolkit để bạn xây dựng gateway theo đúng yêu cầu của mình.
3.1. Cấu hình cơ bản YARP
YARP hoạt động hoàn toàn qua configuration — không cần viết routing logic thủ công. Mỗi route map một URL pattern tới một cluster (nhóm backend instances).
// Program.cs — Minimal API với YARP
var builder = WebApplication.CreateBuilder(args);
// Thêm YARP services
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
// Thêm Rate Limiting
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("api-limit", opt =>
{
opt.PermitLimit = 100;
opt.Window = TimeSpan.FromMinutes(1);
opt.QueueLimit = 10;
});
});
// Thêm Authentication
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer(options =>
{
options.Authority = "https://auth.example.com";
options.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = "my-api"
};
});
var app = builder.Build();
app.UseRateLimiter();
app.UseAuthentication();
app.UseAuthorization();
app.MapReverseProxy();
app.Run();
// appsettings.json — YARP routing configuration
{
"ReverseProxy": {
"Routes": {
"orders-route": {
"ClusterId": "orders-cluster",
"AuthorizationPolicy": "default",
"RateLimiterPolicy": "api-limit",
"Match": {
"Path": "/api/orders/{**catch-all}"
},
"Transforms": [
{ "PathRemovePrefix": "/api/orders" }
]
},
"users-route": {
"ClusterId": "users-cluster",
"Match": {
"Path": "/api/users/{**catch-all}"
},
"Transforms": [
{ "PathRemovePrefix": "/api/users" },
{ "RequestHeader": "X-Forwarded-Prefix", "Set": "/api/users" }
]
}
},
"Clusters": {
"orders-cluster": {
"LoadBalancingPolicy": "RoundRobin",
"HealthCheck": {
"Active": {
"Enabled": true,
"Interval": "00:00:30",
"Timeout": "00:00:10",
"Path": "/health"
}
},
"Destinations": {
"orders-1": { "Address": "https://orders-1:5001" },
"orders-2": { "Address": "https://orders-2:5002" }
}
},
"users-cluster": {
"Destinations": {
"users-1": { "Address": "https://users:5003" }
}
}
}
}
}
3.2. Custom Middleware trên YARP Pipeline
Điểm mạnh lớn nhất của YARP so với các gateway khác: bạn có toàn quyền kiểm soát ASP.NET Core middleware pipeline. Có thể viết middleware tùy chỉnh chèn vào bất kỳ vị trí nào trong pipeline.
// Custom middleware: API Key validation cho partner routes
app.MapReverseProxy(proxyPipeline =>
{
proxyPipeline.Use(async (context, next) =>
{
var route = context.GetReverseProxyFeature().Route;
if (route.Config.RouteId.StartsWith("partner-"))
{
if (!context.Request.Headers
.TryGetValue("X-API-Key", out var apiKey)
|| !await ValidateApiKey(apiKey!))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsJsonAsync(
new { error = "Invalid API key" });
return;
}
}
await next();
});
// Thêm passive health check
proxyPipeline.UsePassiveHealthChecks();
});
3.3. Health Checks — Active và Passive
YARP hỗ trợ hai loại health check để đảm bảo traffic chỉ đến instances khỏe mạnh:
Active Health Check
Gateway chủ động gọi endpoint /health của mỗi destination theo interval cố định (mặc định 30 giây). Nếu destination không phản hồi hoặc trả status code lỗi, nó bị đánh dấu unhealthy và loại khỏi load balancer rotation. Khi recover, tự động thêm lại.
Passive Health Check
Phát hiện lỗi tại thời điểm request. Nếu destination trả về lỗi (5xx, timeout), YARP đếm failure rate. Khi vượt ngưỡng (ví dụ: 3 lỗi trong 60 giây), destination bị tạm loại khỏi pool. Hoạt động giống circuit breaker — không cần gọi thêm health endpoint.
4. So sánh các API Gateway phổ biến 2026
| Tiêu chí | YARP (.NET) | Kong (OSS) | AWS API Gateway | Envoy |
|---|---|---|---|---|
| Kiểu triển khai | Library (in-process) | Standalone / K8s | Managed service | Sidecar / Standalone |
| Ngôn ngữ | C# / .NET | Lua + Nginx/Kong | N/A (managed) | C++ / WASM filters |
| Performance overhead | <1ms (in-process) | 1-5ms (proxy hop) | 5-29ms (managed) | ~1ms (sidecar) |
| Customization | Full middleware pipeline | Plugin system (Lua/Go) | Lambda authorizers | WASM / Lua filters |
| Rate Limiting | .NET native (từ .NET 7) | Built-in plugin | Built-in (throttling) | Local/Global filters |
| Service Discovery | Config / Custom provider | DNS / Consul / K8s | VPC Link / ALB | xDS API (Istio) |
| Health Check | Active + Passive | Active (upstream) | Managed | Active + Passive + EDS |
| Chi phí | Miễn phí (OSS) | Miễn phí (OSS) / Enterprise | $3.50/triệu request | Miễn phí (OSS) |
| Phù hợp với | .NET team, full control | Multi-language, plugins | AWS-native, serverless | K8s / Service Mesh |
💡 Chọn gateway nào?
Team .NET, muốn full control: YARP — chạy in-process, zero network hop, customize thoải mái bằng C# middleware. Team đa ngôn ngữ, cần plugin ecosystem: Kong — hệ sinh thái plugin phong phú, admin API mạnh. Full AWS, không muốn quản lý infra: AWS API Gateway — managed, auto-scale, tích hợp Lambda. Kubernetes/Service Mesh: Envoy — data plane chuẩn cho Istio, WASM extensibility.
5. Authentication tại Gateway Layer
Một trong những lợi ích lớn nhất của API Gateway là tập trung authentication. Thay vì mỗi service tự validate JWT, gateway validate một lần rồi forward claims (user ID, roles) xuống downstream qua header.
sequenceDiagram
participant C as Client
participant GW as API Gateway
participant IDP as Identity Provider
participant SVC as Backend Service
C->>GW: Request + Bearer Token
GW->>IDP: Validate JWT (cached JWKS)
IDP-->>GW: Token Valid + Claims
GW->>GW: Check Authorization Policy
GW->>SVC: Forward Request + X-User-Id + X-Roles
SVC-->>GW: Response
GW-->>C: Response
Note over GW: Gateway cache JWKS keys
để giảm roundtrip đến IDP
// YARP: Forward user claims xuống backend service qua header transforms
{
"Routes": {
"secured-route": {
"ClusterId": "backend",
"AuthorizationPolicy": "authenticated-users",
"Match": { "Path": "/api/secure/{**catch-all}" },
"Transforms": [
{ "RequestHeader": "X-User-Id", "Set": "{Claims:sub}" },
{ "RequestHeader": "X-User-Email", "Set": "{Claims:email}" },
{ "RequestHeader": "X-User-Roles", "Set": "{Claims:role}" },
{ "RequestHeaderRemove": "Authorization" }
]
}
}
}
⚠ Luôn remove Authorization header khi forward
Sau khi gateway validate token, nên strip header Authorization trước khi forward xuống backend. Lý do: (1) Backend không cần validate lại, (2) Tránh token leak nếu backend log request headers, (3) Giảm attack surface — nếu backend bị compromise, attacker không lấy được bearer token từ request.
6. Rate Limiting — Bảo vệ Backend
6.1. Các thuật toán Rate Limiting
| Thuật toán | Cách hoạt động | Ưu điểm | Nhược điểm |
|---|---|---|---|
| Fixed Window | Đếm request trong window cố định (ví dụ: 100 req/phút) | Đơn giản, ít memory | Burst ở biên window (199 req trong 2 giây) |
| Sliding Window | Window trượt liên tục, weighted count | Smooth hơn fixed window | Phức tạp hơn, cần lưu timestamp |
| Token Bucket | Token được thêm đều đặn, mỗi request tiêu 1 token | Cho phép burst ngắn, smooth overall | Cần tune bucket size + refill rate |
| Concurrency Limiter | Giới hạn số request đồng thời (parallel) | Bảo vệ khỏi slow-request attack | Không limit throughput tổng thể |
// .NET 10: Rate Limiting đa tầng trong YARP
builder.Services.AddRateLimiter(options =>
{
// Global: 1000 req/phút cho toàn gateway
options.GlobalLimiter = PartitionedRateLimiter
.Create<HttpContext, string>(context =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: "global",
factory: _ => new FixedWindowRateLimiterOptions
{
PermitLimit = 1000,
Window = TimeSpan.FromMinutes(1)
}));
// Per-user: 100 req/phút theo user ID
options.AddPolicy("per-user", context =>
RateLimitPartition.GetTokenBucketLimiter(
partitionKey: context.User?.FindFirst("sub")?.Value
?? context.Connection.RemoteIpAddress?.ToString()
?? "anonymous",
factory: _ => new TokenBucketRateLimiterOptions
{
TokenLimit = 100,
ReplenishmentPeriod = TimeSpan.FromMinutes(1),
TokensPerPeriod = 100,
QueueLimit = 10
}));
// Strict: cho endpoint nhạy cảm (login, password reset)
options.AddFixedWindowLimiter("strict", opt =>
{
opt.PermitLimit = 5;
opt.Window = TimeSpan.FromMinutes(15);
});
options.OnRejected = async (context, ct) =>
{
context.HttpContext.Response.StatusCode = 429;
context.HttpContext.Response.Headers
.RetryAfter = "60";
await context.HttpContext.Response.WriteAsJsonAsync(
new { error = "Too many requests. Retry after 60 seconds." }, ct);
};
});
7. Load Balancing và Circuit Breaker
7.1. Chiến lược Load Balancing trong YARP
YARP hỗ trợ nhiều thuật toán load balancing, cấu hình tại cluster level:
| Policy | Mô tả | Use case |
|---|---|---|
| RoundRobin | Luân phiên qua từng destination | Instances đồng nhất về capacity |
| Random | Chọn destination ngẫu nhiên | Simple, stateless |
| LeastRequests | Chọn destination có ít active request nhất | Instances không đồng nhất, request duration khác nhau |
| PowerOfTwoChoices | Random 2 destinations, chọn cái ít request hơn | Balance tốt giữa randomness và load-awareness |
| FirstAlphabetical | Luôn chọn destination đầu tiên theo alphabet | Primary-secondary failover |
7.2. Circuit Breaker tại Gateway
Khi một backend service bị lỗi liên tục, gateway không nên tiếp tục gửi request đến nó — sẽ gây cascade failure. Circuit Breaker pattern giải quyết vấn đề này:
stateDiagram-v2
[*] --> Closed
Closed --> Open : Failure threshold reached
Open --> HalfOpen : Timeout expires
HalfOpen --> Closed : Probe request succeeds
HalfOpen --> Open : Probe request fails
state Closed {
[*] --> Monitoring
Monitoring --> Monitoring : Request OK (reset counter)
Monitoring --> CountFailure : Request Failed
CountFailure --> Monitoring : Below threshold
}
// Kết hợp YARP với Polly cho Circuit Breaker
builder.Services.AddHttpClient("yarp-forwarder")
.AddResilienceHandler("gateway-resilience", pipeline =>
{
pipeline.AddCircuitBreaker(new()
{
SamplingDuration = TimeSpan.FromSeconds(30),
FailureRatio = 0.5,
MinimumThroughput = 10,
BreakDuration = TimeSpan.FromSeconds(15)
});
pipeline.AddTimeout(TimeSpan.FromSeconds(10));
pipeline.AddRetry(new()
{
MaxRetryAttempts = 2,
Delay = TimeSpan.FromMilliseconds(500),
BackoffType = DelayBackoffType.Exponential,
ShouldHandle = new PredicateBuilder()
.Handle<HttpRequestException>()
.Handle<TimeoutRejectedException>()
});
});
8. Backend-for-Frontend (BFF) Pattern — Triển khai thực tế
BFF pattern tạo một gateway riêng cho mỗi loại client, cho phép tùy chỉnh response format, aggregation logic và caching strategy theo đúng nhu cầu từng platform.
graph TB
subgraph "Client Layer"
WEB[Vue.js SPA]
MOB[React Native App]
IOT[IoT Dashboard]
end
subgraph "BFF Layer"
WBFF[Web BFF
Full response, SSR support]
MBFF[Mobile BFF
Compact response, pagination]
IBFF[IoT BFF
Minimal payload, batch writes]
end
subgraph "Domain Services"
USER[User Service]
ORDER[Order Service]
PRODUCT[Product Service]
ANALYTICS[Analytics Service]
end
WEB --> WBFF
MOB --> MBFF
IOT --> IBFF
WBFF --> USER
WBFF --> ORDER
WBFF --> PRODUCT
WBFF --> ANALYTICS
MBFF --> USER
MBFF --> ORDER
MBFF --> PRODUCT
IBFF --> ANALYTICS
style WBFF fill:#e94560,stroke:#fff,color:#fff
style MBFF fill:#e94560,stroke:#fff,color:#fff
style IBFF fill:#e94560,stroke:#fff,color:#fff
style USER fill:#2c3e50,stroke:#fff,color:#fff
style ORDER fill:#2c3e50,stroke:#fff,color:#fff
style PRODUCT fill:#2c3e50,stroke:#fff,color:#fff
style ANALYTICS fill:#2c3e50,stroke:#fff,color:#fff
// Web BFF: Aggregation endpoint cho Dashboard page
app.MapGet("/bff/dashboard", async (
IUserService userService,
IOrderService orderService,
IProductService productService,
HttpContext context) =>
{
var userId = context.User.FindFirst("sub")!.Value;
// Gọi song song 3 services
var profileTask = userService.GetProfileAsync(userId);
var ordersTask = orderService.GetRecentAsync(userId, limit: 10);
var recommendationsTask = productService
.GetRecommendationsAsync(userId, limit: 8);
await Task.WhenAll(profileTask, ordersTask, recommendationsTask);
return Results.Ok(new
{
Profile = profileTask.Result,
RecentOrders = ordersTask.Result,
Recommendations = recommendationsTask.Result,
ServerTime = DateTime.UtcNow
});
}).RequireAuthorization();
// Mobile BFF: Compact response, chỉ trả fields cần thiết
app.MapGet("/bff/mobile/dashboard", async (
IUserService userService,
IOrderService orderService,
HttpContext context) =>
{
var userId = context.User.FindFirst("sub")!.Value;
var profileTask = userService.GetProfileAsync(userId);
var ordersTask = orderService.GetRecentAsync(userId, limit: 5);
await Task.WhenAll(profileTask, ordersTask);
var profile = profileTask.Result;
return Results.Ok(new
{
DisplayName = profile.DisplayName,
AvatarUrl = profile.AvatarUrl,
OrderCount = ordersTask.Result.Count,
LastOrderStatus = ordersTask.Result.FirstOrDefault()?.Status
});
}).RequireAuthorization();
9. Observability — Monitoring API Gateway
API Gateway là nơi tốt nhất để đặt observability vì tất cả traffic đều đi qua đây. Cần monitor 4 metrics chính (RED + Saturation):
// OpenTelemetry integration cho YARP
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddMeter("Yarp.ReverseProxy")
.AddOtlpExporter(opt =>
opt.Endpoint = new Uri("http://otel-collector:4317"));
})
.WithTracing(tracing =>
{
tracing.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService("api-gateway"))
.AddOtlpExporter();
});
// Custom middleware: add correlation ID
app.Use(async (context, next) =>
{
if (!context.Request.Headers.ContainsKey("X-Correlation-Id"))
{
context.Request.Headers["X-Correlation-Id"] =
Guid.NewGuid().ToString("N");
}
context.Response.Headers["X-Correlation-Id"] =
context.Request.Headers["X-Correlation-Id"];
await next();
});
10. Best Practices cho Production
💡 10 nguyên tắc thiết kế API Gateway cho Production
- Stateless gateway: Không lưu session state tại gateway — dùng JWT hoặc external session store. Cho phép horizontal scale dễ dàng.
- Timeout cascade: Gateway timeout phải lớn hơn backend timeout. Ví dụ: backend 5s → gateway 8s → client 15s. Tránh gateway timeout trước khi backend trả response.
- Retry chỉ cho idempotent operations: Chỉ retry GET, PUT, DELETE. KHÔNG retry POST (có thể tạo duplicate). Nếu cần retry POST, yêu cầu client gửi Idempotency-Key header.
- Rate limit trước auth: Đặt rate limiting ở đầu pipeline để chặn abuse sớm nhất, trước khi tốn CPU cho JWT validation.
- Health check riêng cho gateway: Tách
/health/live(gateway alive) và/health/ready(gateway + backends ready). Kubernetes dùng liveness và readiness probe khác nhau. - Request/Response size limits: Set max body size (ví dụ: 10MB) để chặn payload abuse. Dùng streaming cho file upload thay vì buffer toàn bộ.
- Graceful shutdown: Khi gateway restart, drain active connections trước khi shutdown. YARP hỗ trợ
app.Lifetime.ApplicationStoppingevent. - Configuration hot-reload: Thay đổi routing không cần restart gateway. YARP hỗ trợ
IProxyConfigProviderđể load config từ DB, Consul hoặc etcd. - Tránh gateway monolith: Không đặt business logic vào gateway. Gateway chỉ xử lý cross-cutting concerns — routing, auth, rate limit, transform. Business logic thuộc về domain services.
- Canary routing: Dùng header-based hoặc weight-based routing để rollout version mới dần dần. YARP hỗ trợ
HeaderRouteMatchđể route theo custom header.
11. Kiến trúc tổng thể — Gateway trong Production Stack
graph TB
CDN[CDN / Cloudflare] --> LB[External Load Balancer]
LB --> GW1[API Gateway Instance 1]
LB --> GW2[API Gateway Instance 2]
subgraph "Gateway Responsibilities"
GW1 --> |"Auth, Rate Limit,
Route, Transform"| GW1
end
GW1 --> SD[Service Discovery
Consul / K8s DNS]
GW2 --> SD
SD --> US1[User Service x3]
SD --> OS1[Order Service x2]
SD --> PS1[Product Service x4]
GW1 --> OTEL[OpenTelemetry
Collector]
GW2 --> OTEL
OTEL --> GRAF[Grafana / Dashboard]
style CDN fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50
style LB fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style GW1 fill:#e94560,stroke:#fff,color:#fff
style GW2 fill:#e94560,stroke:#fff,color:#fff
style SD fill:#2c3e50,stroke:#fff,color:#fff
style US1 fill:#2c3e50,stroke:#fff,color:#fff
style OS1 fill:#2c3e50,stroke:#fff,color:#fff
style PS1 fill:#2c3e50,stroke:#fff,color:#fff
style OTEL fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style GRAF fill:#f8f9fa,stroke:#e94560,color:#2c3e50
Kết luận
API Gateway không phải là một component tùy chọn trong microservices — nó là lớp hạ tầng bắt buộc khi hệ thống vượt quá 3-5 services. Bằng cách tập trung routing, authentication, rate limiting và observability vào một điểm duy nhất, gateway giúp team tập trung vào business logic thay vì lặp đi lặp lại cross-cutting concerns ở mỗi service.
Với .NET team, YARP là lựa chọn nổi bật nhờ chạy in-process trên ASP.NET Core pipeline — overhead gần như bằng 0 và tùy chỉnh không giới hạn bằng C# middleware. Với team đa ngôn ngữ hoặc cần plugin ecosystem sẵn có, Kong vẫn là tiêu chuẩn ngành. Còn nếu đã all-in AWS và muốn zero ops, AWS API Gateway là lựa chọn managed đáng cân nhắc.
Dù chọn giải pháp nào, hãy nhớ nguyên tắc vàng: Gateway chỉ xử lý cross-cutting concerns. Business logic thuộc về domain services.
Tài liệu tham khảo
- Microsoft Learn — Getting Started with YARP on .NET 10
- Milan Jovanović — Implementing an API Gateway with YARP
- NashTech — Build Full Sample with YARP API Gateway on .NET 10
- Calmops — API Gateways: Kong, Envoy and Modern API Management 2026
- Elysiate — API Gateway Authentication Patterns 2026: JWT, OAuth2, API Keys, mTLS
- GitHub — dotnet/yarp: A toolkit for developing high-performance HTTP reverse proxy applications
- AntonDevTips — YARP as API Gateway in .NET: 7 Real-World Scenarios
Microsoft Agent Framework 1.0 — SDK Thống Nhất Cho AI Agents Trên .NET 10
DynamoDB Single-Table Design: Nghệ thuật thiết kế NoSQL cho hệ thống quy mô lớn
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.