簡介
API 是服務之間以及後端和前端之間的合約。選擇正確的API風格和良好的設計決定了微服務架構的成敗。本文深入探討了 3 種最受歡迎的 API 樣式,並說明如何為每個用例選擇正確的 API 樣式。
1. REST API — 預設選擇
1.1 RESTful 最佳實踐
基於資源的 URL:
GET /api/v1/products → List products
GET /api/v1/products/{id} → Get product
POST /api/v1/products → Create product
PUT /api/v1/products/{id} → Update product
PATCH /api/v1/products/{id} → Partial update
DELETE /api/v1/products/{id} → Delete product
GET /api/v1/products/{id}/reviews → Nested resource
分頁(基於遊標):
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTAwfQ==",
"has_more": true,
"total": 1500
}
}
標準錯誤回應:
{
"error": {
"code": "PRODUCT_NOT_FOUND",
"message": "Product with id '123' not found",
"details": []
}
}
1.2 API 版本控制策略
| 戰略 | 範例 | 優點 | 缺點 |
|---|---|---|---|
| 網址路徑 | /api/v1/products | 明確、易於路由 | 網址更改 |
| 標題 | Accept: application/vnd.api.v2+json | 乾淨的網址 | 隱藏 |
| 查詢參數 | /api/products?version=2 | 簡單 | 凌亂 |
推薦: URL 路徑版本控制 — 簡單、清晰、易於在 API 閘道上路由。
1.3 何時使用 REST
- 第三方公共API
- 簡單的CRUD操作
- 關鍵快取(HTTP 本機快取)
- 熟悉的團隊,成熟的工具
2. GraphQL-靈活的查詢
2.1 為什麼微前端要用 GraphQL?
每個微前端都需要來自同一服務的不同的資料:
# Product MFE (cần đầy đủ thông tin)
query ProductDetail {
product(id: "123") {
id, name, description, price
images { url, alt }
reviews { rating, comment, user { name } }
relatedProducts { id, name, price }
}
}
# Cart MFE (chỉ cần tên + giá)
query CartItem {
product(id: "123") {
id, name, price, thumbnail
}
}
→ GraphQL 解決了過度獲取(REST 返回太多)和不足獲取(REST 需要調用許多端點)的問題。
2.2 模式設計最佳實踐
type Product {
id: ID!
name: String!
slug: String!
price: Money!
images: [Image!]!
category: Category!
reviews(first: Int, after: String): ReviewConnection!
}
type Money {
amount: Float!
currency: Currency!
}
type ReviewConnection {
edges: [ReviewEdge!]!
pageInfo: PageInfo!
}
2.3 何時使用 GraphQL
- 前端需要資料取得的靈活性
- 多個前端客戶端需要不同的數據
- BFF層或API網關聚合
- 複雜的嵌套資料關係
3. gRPC — 高效能內部
3.1 協定緩衝區
// product.proto
syntax = "proto3";
service ProductService {
rpc GetProduct(GetProductRequest) returns (Product);
rpc ListProducts(ListProductsRequest) returns (stream Product);
rpc CreateProduct(CreateProductRequest) returns (Product);
}
message Product {
string id = 1;
string name = 2;
double price = 3;
repeated string image_urls = 4;
}
message GetProductRequest {
string id = 1;
}
3.2 gRPC 優勢
- ~比 JSON 序列化(二進位格式)快 10 倍
- HTTP/2:多重化、標頭壓縮
- 強型別:產生的程式碼,編譯時檢查
- 雙向流:即時資料流
3.3 何時使用 gRPC
- 服務到服務通訊(僅限內部)
- 高吞吐量、低延遲要求
- 串流資料(即時更新、日誌)
- 多語言:Go、Java、Python、Node.js 的程式碼生成
4.決策矩陣
| 標準 | 休息 | GraphQL | gRPC |
|---|---|---|---|
| 主要用途 | 外部 API、CRUD | 前端查詢 | 服務到服務 |
| 性能 | 好 | 好 | 優 |
| 快取 | HTTP 原生 | 複雜(持久查詢) | 手冊 |
| 學習曲線 | 低 | 中 | 高 |
| 前端友善 | 是的 | 非常 | 否(需要代理) |
| 串流媒體 | SSE/WebSocket | 訂閱 | 本地 |
| 工具 | 優 | 好 | 成長 |
| 瀏覽器支援 | 本地 | 本地 | 需要 gRPC-Web |
4.1 電商平台建議
Client → Shell/MFE: GraphQL (flexible, typed)
MFE → BFF/Gateway: REST hoặc GraphQL
Gateway → Services: REST (simple CRUD) + gRPC (high-perf)
Service → Service: gRPC (internal) + Events (async)
總結
- REST:外部API和簡單CRUD的預設選擇
- GraphQL:非常適合微前端 - 減少過度/不足的獲取
- gRPC:服務到服務之王 — 快速、類型化、串流媒體
- 實務上:使用所有 3 種方法的組合來實現正確的用例
下一篇文章: 第 6 課:服務間通訊 — 同步、非同步與事件驅動