RPC 與 gRPC

核心定義

RPC(Remote Procedure Call)是一種 通訊模型:允許程式呼叫 遠端伺服器上的函式,像呼叫本地函式一樣

核心理念

隱藏網路細節,讓遠端方法呼叫看起來像本地呼叫。

設計導向 REST GraphQL RPC
中心 Resource Query Method(方法)
API 形式 URI 操作 Query 語言 直接呼叫 function
典型用途 對外 API 對外 API 對內微服務通訊

核心特徵

1. 方法導向(Method-oriented)

API 以「動作」為中心,而非資源:

REST:  GET /users/123
gRPC:  userService.GetUser(id=123)

2. 跨語言協定支援

透過 IDL(Interface Definition Language) 定義介面:

syntax = "proto3";

service UserService {
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
  rpc CreateUser(CreateUserRequest) returns (CreateUserResponse);
}

message GetUserRequest {
  int64 id = 1;
}

message GetUserResponse {
  int64 id = 1;
  string name = 2;
  string email = 3;
}

.proto 生成 stub / client library,不同語言都能互相呼叫(Go ↔ Python ↔ Java)。

3. 高效序列化格式

格式 類型 範例大小 吞吐量
JSON 文字 {"id":"123","name":"Terry"} = ~40 bytes 1x(基準)
Protobuf 二進位 同等內容 ≈ 15 bytes ~10x
Thrift / Avro 二進位 類似 Protobuf ~10x
為什麼 Protobuf 這麼快?

  • 無欄位名稱(用 tag number 1, 2, 3...)
  • 可變長度編碼(varint)— 小數字佔更少 byte
  • Schema 事先知道 → 不需解析結構

4. 雙向串流(Bidirectional Streaming)

gRPC 基於 HTTP/2,支援四種呼叫模式:

模式 Client → Server Server → Client 例子
Unary 1 1 一般 RPC call
Server streaming 1 N 訂閱事件
Client streaming N 1 上傳大量資料
Bidirectional N N 聊天室、即時協作

gRPC 使用流程

1. 定義 .proto                    2. 執行 protoc 生成 stub
   ┌──────────────┐                  ┌──────────────────┐
   │ user.proto   │ ──protoc──►     │ user_pb2.py      │
   │ service ...  │                  │ user_pb2_grpc.py │
   └──────────────┘                  │ user.pb.go       │
                                     │ User.java        │
                                     └──────────────────┘

3. Client 呼叫(像本地函式)
   ┌────────────────────────────────────────┐
   │ user = client.GetUser(GetUserRequest(  │
   │     id=123                             │
   │ ))                                     │
   │ # 底層透過 HTTP/2 + Protobuf 傳輸      │
   └────────────────────────────────────────┘

優點

優點 說明
呼叫直觀 對開發者像在呼叫本地函式
效能高 二進位序列化 + HTTP/2 多工 → 吞吐量 ~10x JSON/REST
強型別 IDL 提供清晰契約,跨語言型別安全
支援串流 Bidirectional streaming 適合 real-time

缺點

缺點 說明
耦合度高 Client/Server 都依賴相同 IDL,版本演進需規劃
不如 REST 通用 需預先生成 stub;無法像 REST 用 curl 直接測試
Debug 困難 Protobuf 是二進位,不像 JSON 可讀
對外開放性差 瀏覽器原生不支援 gRPC(需要 gRPC-Web 代理)
浏览器限制 HTTP/2 trailers 在瀏覽器不開放,需轉譯層

RPC 版本演進

Protobuf 有設計規則避免破壞相容性:

message User {
  int64 id = 1;
  string name = 2;
  // reserved 3;  // 舊欄位刪除後保留 tag
  string email = 4;  // 新增欄位要用新 tag number
}

相容規則


面試中如何談 RPC

  1. 典型使用場景
    • 微服務之間的內部通訊 → gRPC 是業界標準
    • 高效能、低延遲、大量呼叫
    • 需要 streaming(聊天、監控、資料管道)
  2. 對外公開 API:通常用 REST/GraphQL(直觀、跨平台、好 debug)
  3. 對內服務間通訊:多選 RPC(效能好、IDL 保證一致性)
面試口訣

「REST/GraphQL 對外,gRPC 對內」 — 這是業界常見的混合策略。

陷阱:過早跳 gRPC

面試官要看你思考問題的過程。在沒有明確效能瓶頸前就選 gRPC,會顯得在「為了用而用」。
正確順序:先 REST → 確認內部服務有效能瓶頸 → 再提 gRPC。


Simplification-with-exceptions

邊界情況

  • gRPC 不是唯一 RPC:還有 Thrift(Facebook)、Avro(Apache)、JSON-RPC、XML-RPC
  • gRPC-Web:讓瀏覽器用 gRPC,但需代理(Envoy)做 HTTP/1 ↔ HTTP/2 轉換
  • 對外也能用 gRPC:B2B 合作夥伴(雙方都是服務)可用 gRPC + mTLS
  • Debug 工具在進步:grpcurl、BloomRPC、Postman 都支援 gRPC