RPC 使用中的一些注意點
最近線上碰到一點小問題,分析其原因發(fā)現(xiàn)是出在對 RPC 使用上的一些細節(jié)掌握不夠清晰導致。很多時候我們做業(yè)務開發(fā)會把 RPC 當作黑盒機制來使用,但若不對黑盒的工作原理有個基本掌握,也容易犯一些誤用的微妙錯誤。
雖然曾經已經寫過一篇《RPC 的概念模型與實現(xiàn)解析》 從概念模型和實現(xiàn)細節(jié)上講述了 RPC 的原理,這一篇就從使用上的一些注意點來捋一捋吧。
同步
RPC 的調用通常為了方便使用,會被偽裝成普通方法調用的形式。但實際二者之間存在巨大的差異,進程內的方法調用的時間量級是 ns(納秒),而進程間的 RPC 方法調用時間量級通常是 ms(毫秒),它們之間差著 10 的六次方呢。RPC 的冰山底部透視圖如下:
但在目前流行的微服務架構模式下,跨服務的同步調用隱藏著巨大的風險。一般微服務化架構下,通常一個業(yè)務的調用會跨 N(N 一般大于 2) 個服務進程,整個調用鏈路上的同步調用等待的瓶頸會由最慢(或脆弱)的服務決定,A-B-C 像這樣一個鏈路,A 同步調用 B 并等待返回,B 同步調用 C 并等待返回,以此類推,就像一組齒輪鏈,級級傳動,這很容易產生雪崩效應。若 C 服務掛住了,會導致前面的服務全部都因為等待超時而占用大量不必要的線程資源。
因此,微服務架構下,內部主服務鏈之間的 RPC 調用需要異步化,服務之間的調用請求和等待結果相互之間解耦,如下是一個服務鏈路調用的示意圖:
外部用戶通過服務網關(API Gateway)發(fā)起調用并等待結果,隨后網關派發(fā)調用請求給后續(xù)服務,其主調用鏈路為 A-B-C,其內部為異步調用,鏈路上不等待,最后由 C 返回結果給服務網關。其中 B 又依賴兩個子服務,S1 和 S2,B 需要 S1 和 S2 的返回結果才能發(fā)起 C 調用,因此在支線上 B 針對 S1 和 S2 調用就需要是同步的。
異步
RPC 的同步調用確保請求送達對方并收到對方響應,若沒有收到響應,框架則拋出 Timeout 異常。這種情況下調用方是無法確定調用是成功還是失敗的,需要根據業(yè)務場景(是否可重入,冪等)選擇重試和補償策略。
而 RPC 的異步調用意味著 RPC 框架不阻塞調用方線程,調用方不需要立刻拿到返回結果,甚至調用方根本就不關心返回結果。RPC 的異步交互場景示意圖如下: