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