為什麼要有 gRPC
微服務架構裡,order-service 呼叫 inventory-service 呼叫 payment-service——這些服務之間的通信如果每次都是 HTTP/1.1 + JSON,在高 QPS 下有三個問題:
- 序列化成本:JSON 是文字格式,序列化和反序列化有 CPU 開銷
- 協議開銷:HTTP/1.1 的 header 很冗餘,每個請求都要帶完整 header
- 缺少型別約束:JSON 沒有 schema,服務之間的 API 合約是隱式的,很容易不同步
gRPC 解決這三個問題:Protobuf(二進位格式)+ HTTP/2(多路復用)+ 強型別 schema。
Protocol Buffers(Protobuf)
Protobuf 是 gRPC 的序列化格式。先定義 schema(.proto 文件),再生成各語言的 code:
// order.proto
syntax = "proto3";
package order;
service OrderService {
rpc CreateOrder (CreateOrderRequest) returns (CreateOrderResponse);
rpc GetOrder (GetOrderRequest) returns (Order);
rpc StreamOrders (StreamOrdersRequest) returns (stream Order); // streaming
}
message CreateOrderRequest {
string user_id = 1;
repeated OrderItem items = 2;
}
message CreateOrderResponse {
string order_id = 1;
string status = 2;
}
message Order {
string id = 1;
string user_id = 2;
float total = 3;
OrderStatus status = 4;
}
enum OrderStatus {
PENDING = 0;
SHIPPED = 1;
DELIVERED = 2;
}# 生成 code(需要 protoc 和對應語言的 plugin)
protoc --go_out=. --go-grpc_out=. order.proto
protoc --python_out=. --grpc_python_out=. order.proto四種通信模式
Unary RPC:一個 request,一個 response(最常用)。
Server Streaming:一個 request,多個 response(server 推資料流,如訂單狀態追蹤)。
Client Streaming:多個 request,一個 response(client 上傳資料流,如批次上傳)。
Bidirectional Streaming:雙向流(即時聊天、遊戲狀態同步)。
gRPC vs REST vs GraphQL
| REST | GraphQL | gRPC | |
|---|---|---|---|
| 適合 | 公開 API,外部整合 | 靈活的資料查詢,前端 | 服務間內部通信 |
| 協議 | HTTP/1.1 | HTTP/1.1 | HTTP/2 |
| 序列化 | JSON(文字) | JSON(文字) | Protobuf(二進位) |
| 型別 | 無 schema | 有 schema | 有 schema |
| 瀏覽器支援 | 原生 | 原生 | 需要 gRPC-Web proxy |
| 效能 | 普通 | 普通 | 高(2-5x faster) |
最常見的架構:對外(瀏覽器、第三方)用 REST 或 GraphQL;服務之間的內部通信用 gRPC。
什麼時候不用 gRPC
- 公開 API:gRPC 需要 client 有 Protobuf,外部開發者接 REST 容易得多
- 瀏覽器直連:瀏覽器不原生支援 gRPC(需要 gRPC-Web 或 Connect protocol)
- 快速原型:Protobuf schema 定義和 code generation 有一定的初始成本
Infra/network-edge 章節(I01)和 backend/api-design(B09)有 gRPC 的深入實作。