簡介
在微服務中,服務需要相互通訊。選擇錯誤的通訊模式可能會導致級聯故障、高延遲和緊密耦合。本文分析了所有流行的模式。
1. 同步通信
1.1 休息
GET /api/users/123 HTTP/1.1
Host: user-service
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 123,
"name": "Duy Tran",
"email": "[email protected]"
}
Ưu điểm:
✅ Simple, human-readable
✅ Widely supported
✅ HTTP caching
✅ Dễ debug (curl, Postman)
Nhược điểm:
❌ Over-fetching / Under-fetching
❌ Multiple round trips (N+1)
❌ Text-based → larger payload
1.2 gRPC
// Proto definition
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc ListUsers(ListUsersRequest) returns (stream User);
}
message User {
int64 id = 1;
string name = 2;
string email = 3;
}
Ưu điểm:
✅ Binary (Protobuf) → nhỏ hơn, nhanh hơn
✅ HTTP/2 → multiplexing, streaming
✅ Strongly typed (code generation)
✅ Bi-directional streaming
Nhược điểm:
❌ Không human-readable
❌ Browser support hạn chế (cần grpc-web)
❌ Khó debug hơn REST
1.3 GraphQL
# Client quyết định lấy fields nào
query {
user(id: 123) {
name
orders(last: 5) {
id
total
items {
product { name }
}
}
}
}
# 1 request lấy đúng data cần thiết
# Không over-fetching, không under-fetching
Ưu điểm:
✅ Client-driven queries
✅ Single endpoint
✅ Strongly typed schema
✅ Introspection
Nhược điểm:
❌ Complexity (resolver, dataloader)
❌ Caching khó hơn REST
❌ N+1 queries ở backend
❌ Security (query depth attacks)
1.4 比較
| 特點 | 休息 | gRPC | GraphQL |
|---|---|---|---|
| 協定 | HTTP/1.1+ | HTTP/2 | HTTP |
| 格式 | JSON | 協定緩衝區 | JSON |
| 型別安全 | 弱 | 強 | 強 |
| 串流媒體 | 否(上交所) | 是的 | 訂閱 |
| 瀏覽器 | 是的 | 有限公司 | 是的 |
| 最適合 | 公共 API | 服務↔服務 | 前端↔後端 |
| 性能 | 中 | 高 | 中 |
2. 非同步通信
2.1 基於訊息(點對點)
Order Service ──message──► Queue ──► Payment Service
Tight contract: Order Service biết Payment Service sẽ xử lý
1 message → 1 consumer
Use case: Task distribution
2.2 基於事件(發布/訂閱)
Order Service ──event──► Topic
│
┌─────────┼─────────┐
▼ ▼ ▼
Payment Inventory Email
Loose coupling: Order Service KHÔNG biết ai subscribe
1 event → N consumers
Use case: Notifications, data sync
2.3 請求-回覆(非同步)
Order Service ──► Request Queue ──► Payment Service
│
Order Service ◄── Reply Queue ◄─────────┘
Correlation ID để match request ↔ reply
Async nhưng vẫn request-response semantic
3. 彈性模式
3.1 斷路器
States:
CLOSED (normal):
Requests đi qua bình thường
Đếm failures
OPEN (tripped):
Failures > threshold → OPEN
Requests bị reject ngay (fail fast)
Không gọi downstream service
HALF-OPEN (testing):
After timeout → cho 1 request thử
Success → CLOSED
Fail → OPEN lại
┌────────┐ failure > 5 ┌────────┐
│ CLOSED │──────────────►│ OPEN │
│ │◄──────────────│ │
└────────┘ success └───┬────┘
│ timeout
┌─────▼─────┐
│ HALF-OPEN │
└───────────┘
3.2 使用指數退避重試
Attempt 1: Fail → Wait 1s
Attempt 2: Fail → Wait 2s
Attempt 3: Fail → Wait 4s
Attempt 4: Fail → Wait 8s + jitter
Attempt 5: Fail → Give up, return error
Jitter: Random delay thêm vào
Tránh "thundering herd" khi nhiều clients retry cùng lúc
Retry Budget:
Max 20% requests là retries
Tránh retry storm amplification
3.3 逾時策略
Cascading timeout:
Client ──(timeout: 5s)──► API Gateway
API Gateway ──(timeout: 3s)──► Order Service
Order Service ──(timeout: 1s)──► Payment Service
Rule: Outer timeout > Inner timeout
Tránh: Client đã timeout nhưng backend vẫn xử lý
3.4 艙壁
Vấn đề: 1 slow service chiếm hết threads → toàn bộ app chậm
Giải pháp: Isolate resource pools
┌─────────────────────────────────────┐
│ Application │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Thread Pool │ │ Thread Pool │ │
│ │ Service A │ │ Service B │ │
│ │ (10 threads)│ │ (10 threads)│ │
│ └─────────────┘ └─────────────┘ │
│ │
│ Service A chậm → Pool A hết │
│ Service B vẫn hoạt động bình thường │
└─────────────────────────────────────┘
4. 服務網格
4.1 邊車模式
Không có Service Mesh:
Service A ──(retry, circuit breaker, mTLS, tracing)──► Service B
Logic phức tạp TRONG code mỗi service
Có Service Mesh:
┌──────────────────┐ ┌──────────────────┐
│ Pod A │ │ Pod B │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Service A │ │ │ │ Service B │ │
│ │ (business │ │ │ │ (business │ │
│ │ logic only) │ │ │ │ logic only) │ │
│ └──────┬───────┘ │ │ └──────▲───────┘ │
│ │ │ │ │ │
│ ┌──────▼───────┐ │ │ ┌──────┴───────┐ │
│ │ Sidecar Proxy│◄├─────────├►│ Sidecar Proxy│ │
│ │ (Envoy) │ │ mTLS │ │ (Envoy) │ │
│ │ retry,circuit│ │ │ │ retry,circuit│ │
│ │ trace,metrics│ │ │ │ trace,metrics│ │
│ └──────────────┘ │ │ └──────────────┘ │
└──────────────────┘ └──────────────────┘
Control Plane (Istio/Linkerd):
Config policies, certificates, routing rules
5. API 版本控制
1. URL versioning:
/api/v1/users → Version 1
/api/v2/users → Version 2
Simple, explicit
2. Header versioning:
Accept: application/vnd.myapp.v2+json
Clean URLs
3. Query parameter:
/api/users?version=2
Easy to test
4. No versioning (evolution):
Thêm fields mới (backward compatible)
Deprecate old fields (nhưng không remove)
GraphQL style
總結
| 圖案 | 何時使用 |
|---|---|
| 休息 | 公共API,簡單的CRUD |
| gRPC | 服務 ↔ 服務,效能至關重要 |
| GraphQL | 複雜的前端查詢 |
| 非同步/事件 | 鬆散耦合,最終一致性 |
| 斷路器 | 防止級聯故障 |
| 服務網格 | 服務眾多,網路複雜 |
練習
-
協議選擇: 微服務:API閘道→使用者服務、訂單服務→庫存服務、前端→BFF。為每對選擇 REST/gRPC/GraphQL。解釋。
-
斷路器配置: 支付服務的 SLA 為 99.9%(每月 43 分鐘停機時間)。設計斷路器配置:故障閾值、逾時、半開請求、恢復時間。
-
彈性設計: 服務 A 呼叫服務 B(關鍵)、服務 C(可選)。為每個依賴設計重試+逾時+回退策略。