RPC 使用中的一些注意點

最近線上碰到一點小問題,分析其緣由發現是出在對 RPC 使用上的一些細節掌握不夠清晰致使。不少時候咱們作業務開發會把 RPC 看成黑盒機制來使用,但若不對黑盒的工做原理有個基本掌握,也容易犯一些誤用的微妙錯誤。微信

雖然曾經已經寫過一篇《RPC 的概念模型與實現解析》 從概念模型和實現細節上講述了 RPC 的原理,這一篇就從使用上的一些注意點來捋一捋吧。網絡

同步

RPC 的調用一般爲了方便使用,會被假裝成普通方法調用的形式。但實際兩者之間存在巨大的差別,進程內的方法調用的時間量級是 ns(納秒),而進程間的 RPC 方法調用時間量級一般是 ms(毫秒),它們之間差着 10 的六次方呢。RPC 的冰山底部透視圖以下:架構

但在目前流行的微服務架構模式下,跨服務的同步調用隱藏着巨大的風險。通常微服務化架構下,一般一個業務的調用會跨 N(N 通常大於 2) 個服務進程,整個調用鏈路上的同步調用等待的瓶頸會由最慢(或脆弱)的服務決定,A-B-C 像這樣一個鏈路,A 同步調用 B 並等待返回,B 同步調用 C 並等待返回,以此類推,就像一組齒輪鏈,級級傳動,這很容易產生雪崩效應。若 C 服務掛住了,會致使前面的服務所有都由於等待超時而佔用大量沒必要要的線程資源。框架

所以,微服務架構下,內部主服務鏈之間的 RPC 調用須要異步化,服務之間的調用請求和等待結果相互之間解耦,以下是一個服務鏈路調用的示意圖:異步

外部用戶經過服務網關(API Gateway)發起調用並等待結果,隨後網關派發調用請求給後續服務,其主調用鏈路爲 A-B-C,其內部爲異步調用,鏈路上不等待,最後由 C 返回結果給服務網關。其中 B 又依賴兩個子服務,S1 和 S2,B 須要 S1 和 S2 的返回結果才能發起 C 調用,所以在支線上 B 針對 S1 和 S2 調用就須要是同步的。微服務

異步

RPC 的同步調用確保請求送達對方並收到對方響應,若沒有收到響應,框架則拋出 Timeout 異常。這種狀況下調用方是沒法肯定調用是成功仍是失敗的,須要根據業務場景(是否可重入,冪等)選擇重試和補償策略。性能

而 RPC 的異步調用意味着 RPC 框架不阻塞調用方線程,調用方不須要馬上拿到返回結果,甚至調用方根本就不關心返回結果。RPC 的異步交互場景示意圖以下:spa

在上面的示意圖中,對因而否須要返回值的異步請求,其中的細微差別在因而否返回一個 Future 對象給調用方,以便將來(Future)調用方能夠再經過它來獲取返回值。正是由於這種 Future 機制的存在,因此針對前面(圖2)中 S1 和 S2 的調用就能夠採用一種異步並行的調用機制來提高並行性和性能,以下圖所示:線程

這樣調用 S1 和 S2 的總時間就由最慢的一個服務響應時間來決定了。(上圖中其實調用 S1 和 S2 不可能作到同時,有細微的時間差別,但相對跨進程的調用自己來講這種差別基本忽略不計。)對象

線程

RPC 的線程模型通常以下所示:

其中,RPC 的網絡層一般採用非阻塞型 I/O 模型,放在 Java 的實現語境下就是 NIO 了。而 RPC 框架一般共享一個 I/O 線程池,處理全部鏈接上的 I/O 事件派發。一般業務事件會派發到內部的一個固定大小(可配置)的業務執行線程池,再由業務執行線程調用應用實現層的代碼。

但有些 RPC 框架在實現客戶端的 I/O 線程模型時,也採用了針對每一個不一樣的服務端一個獨立的 I/O 線程池,這樣就變成了下面這個圖所示:

這帶來了一個潛在的問題,在一個客戶端須要鏈接大量服務端時(這在基於 RPC 實現的服務框架中很常見),客戶端的 I/O 線程池數就和需鏈接的服務數相等。在如今的微服務部署模式下,通常一個服務部署在一個 Docker 容器中,同一個服務會有不少個(幾十上百個)進程共同組成集羣提供服務,這樣就致使客戶端 I/O 線程數可能會不少。

而在 Docker 環境下 Java 的 Runtime.availableProcessors() 獲取的 CPU 數量實際是物理機的,而不是 Docker 隔離的核數。另外,像 Netty 這樣的網絡框架常常默認是基於 CPU 核數來啓動默認的 I/O 線程數的,因此致使針對每一個服務的客戶端會啓動 CPU 核數個 I/O 線程再乘上服務實例數,這個線程數量也是頗爲客觀,出現單進程好幾千固化的線程,線程調度和切換的成本頗高,另外服務的水平擴展性也有必定的受限。這也是須要注意的另外一點。

...

在曾經那篇《RPC 的概念模型與實現解析》 的的結尾,我曾寫到:

不管 RPC 的概念是如何優雅,可是「草叢中依然有幾條蛇隱藏着」,只有深入理解了 RPC 的本質,才能更好地應用。

因此這一篇大概就是抓出了幾條隱藏着的蛇吧。


寫點文字,畫點畫兒,記錄成長瞬間。
微信公衆號「瞬息之間」,既然碰見,不如一塊兒成長。

相關文章
相關標籤/搜索