為什麼要有 gRPC

微服務架構裡,order-service 呼叫 inventory-service 呼叫 payment-service——這些服務之間的通信如果每次都是 HTTP/1.1 + JSON,在高 QPS 下有三個問題:

  1. 序列化成本:JSON 是文字格式,序列化和反序列化有 CPU 開銷
  2. 協議開銷:HTTP/1.1 的 header 很冗餘,每個請求都要帶完整 header
  3. 缺少型別約束: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

RESTGraphQLgRPC
適合公開 API,外部整合靈活的資料查詢,前端服務間內部通信
協議HTTP/1.1HTTP/1.1HTTP/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 的深入實作。