Remote Procedure Call (RPC)

核心概念

RPC 的目標:讓跨網路的函式呼叫,在程式碼層面看起來跟本地呼叫一模一樣。

你還是寫 k = add(i, j),背後的網路傳輸對你完全不可見。這個透明性靠 Stub 實現。

Stub

Stub 是一個代理(proxy):

  • Client stub:坐落在 client 端,對 client 程式偽裝成真正的函式
  • Server stub:坐落在 server 端,負責接收訊息並呼叫真正的函式

RPC 的完整流程(10 步)

k = add(i, j) 為例:

Client 端出發

  1. Client 程式用正常方式呼叫 client stub
  2. Client stub 把函式名稱和參數**打包(marshal)**成訊息
  3. Client OS 把訊息送往 server

網路傳輸

  1. Server OS 收到訊息,交給 server stub

Server 端執行

  1. Server stub **拆包(unmarshal)**還原參數,呼叫真正的 add()
  2. Server 計算結果,回傳給 server stub

結果回傳

  1. Server stub 把結果打包成訊息,叫 server OS 傳回去
  2. Server OS 把訊息傳到 client OS
  3. Client OS 把訊息交給 client stub
  4. Client stub 拆包結果,直接 return 給 client 程式

對 client 程式而言,整個過程就像呼叫了一個本地函式。

RPC 的三個挑戰

1. 資料格式差異(XDR)

不同架構的電腦對資料的表示方式可能不同,最典型的是 big-endian vs little-endian——同樣的整數,bytes 在記憶體中的排列順序可能相反,直接傳原始 bytes 會解讀錯誤。

解法:用 XDR(External Data Representation) 格式,把資料轉成雙方都認識的中立格式再傳輸。

2. 可靠性(Exactly Once)

本地呼叫幾乎不會失敗,但網路通訊會:封包可能遺失、server 可能當機。

這引發一個微妙問題:如果 client 沒收到回應,是「server 還沒執行」還是「server 執行完但回應遺失」?兩種情況的處理方式完全不同。

語義意義
At most once最多執行一次(不保證有沒有執行到)
Exactly once剛好執行一次(RPC 的理想目標,但難以保證)

3. 找到 Server 的 Port(Matchmaker / Rendezvous)

Port 不應寫死。OS 提供一個 matchmaker 服務

1. Client 問 matchmaker:「RPC X 在哪個 port?」
2. Matchmaker 回傳 port 號 P
3. Client 向 port P 發送實際的 RPC 請求
4. Server daemon 處理請求並回傳結果