はじめに
マイクロサービスでは、サービスは相互に通信する必要があります。間違った通信パターンを選択すると、連鎖的な障害、高い遅延、密結合が発生する可能性があります。この記事では、一般的なパターンをすべて分析します。
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 | グラフQL |
|---|---|---|---|
| プロトコル | HTTP/1.1+ | HTTP/2 | HTTP |
| フォーマット | JSON | プロトブフ | JSON |
| タイプセーフティ | 弱い | 強い | 強い |
| ストリーミング | いいえ (SSE) | はい | 定期購読 |
| ブラウザ | はい | 限定 | はい |
| こんな方に最適 | パブリック 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 イベントベース (Pub/Sub)
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 | サービス ↔ サービス、パフォーマンス重視 |
| グラフQL | 複雑なフロントエンド クエリ |
| 非同期/イベント | 疎結合、結果整合性 |
| サーキットブレーカー | 連鎖的な障害から保護する |
| サービスメッシュ | 多くのサービス、複雑なネットワーキング |
演習
-
プロトコルの選択: マイクロサービス: API ゲートウェイ → ユーザー サービス、注文サービス → インベントリ サービス、フロントエンド → BFF。各ペアに対して REST/gRPC/GraphQL を選択します。説明する。
-
サーキット ブレーカー構成: 支払いサービスには SLA 99.9% (ダウンタイム 43 分/月) があります。サーキット ブレーカー構成の設計: 障害しきい値、タイムアウト、ハーフオープン要求、回復時間。
-
回復力設計: サービス A はサービス B (重要)、サービス C (オプション) を呼び出します。依存関係ごとに再試行 + タイムアウト + フォールバック戦略を設計します。