一不小心實現了RPC 前言 前後對比 繞不開的動態代理 總結

前言


隨着最近關注 cim 項目的人越發增多,導致提的問題以及 Bug 也在增加,在修復問題的過程中難免代碼潔癖又上來了。

看着一兩年前寫的東西總是懷疑這真的是出自自己手裏嘛?有些地方實在忍不住了便開始了漫漫重構之路。

前後對比

在開始之前先簡單介紹一下 cim 這個項目,下面是它的架構圖:

簡單來說就是一個 IM 即時通訊系統,主要有以下部分組成:

  • IM-server 自然就是服務端了,用於和客戶端保持長連接。
  • IM-client 客戶端,可以簡單認爲是類似於的 QQ 這樣的客戶端工具;當然功能肯定沒那麼豐富,只提供了一些簡單消息發送、接收的功能。
  • Route 路由服務,主要用於客戶端鑑權、消息的轉發等;提供一些 http 接口,可以用於查看系統狀態、在線人數等功能。

當然服務端、路由都可以水平擴展。


這是一個消息發送的流程圖,假設現在部署了兩個服務端 A、B 和一個路由服務;其中 ClientAClientB 分別和服務端 A、B 保持了長連接。

ClientAClientB 發送一個 hello world 時,整個的消息流轉如圖所示:

  1. 先通過 http 將消息發送到 Route 服務。
  2. 路由服務得知 ClientB 是連接在 ServerB 上;於是再通過 http 將消息發送給 ServerB
  3. 最終 ServerB 將消息通過與 ClientB 的長連接通道 push 下去,至此消息發送成功。

這裏我截取了 ClientARoute 發起請求的代碼:


可以看到這就是利用 okhttp 發起了一個 http 請求,這樣雖然能實現功能,但其實並不優雅。

舉個例子:假設我們需要對接支付寶的接口,這裏發送一個 http 請求自然是沒問題;但對於支付寶內部各部門直接互相調用接口時那就不應該再使用原始的 http 請求了。

應該是由服務提供方提供一個 api 包,服務消費者只需要依賴這個包就可以實現接口調用。

當然最終使用的是 http、還是自定義私有協議都可以。

也類似於我們在使用 Dubbo 或者是 SpringCloud 時,通常是直接依賴一個 api 包,便可以像調用一個本地方法一樣調用遠程服務了,並且完全屏蔽了底層細節,不管是使用的 http 還是 其他私有協議都沒關係,對於調用者來說完全不關心。

這麼一說是不是有內味了,這不就是 RPC 的官方解釋嘛。

對應到這裏也是同樣的道理,ClientRouteServer 本質上都是一個系統,他們互相的接口調用也應當是走 RPC 才合理。

所以我重構之後的變成這樣了:

是不是代碼也簡潔了許多,就和調用本地方法一樣了,而且這樣也有幾個好處:

  • 完全屏蔽了底層細節,可以更好的實現業務及維護代碼。
  • 即便是服務提供方修改了參數,在編譯期間就能很快發現,而像之前那樣調用是完全不知情的,所以也增加了風險。

繞不開的動態代理

下面來聊聊具體是如何實現的。

其實在上文《動態代理的實際應用》 中也有講到,原理是類似的。

要想做到對調用者無感知,就得創建一個接口的代理對象;在這個代理對象中實現編碼、調用、解碼的過程。

對應到此處其實就是創建一個 routeApi 的代理對象,關鍵就是這段代碼:

RouteApi routeApi = new ProxyManager<>(RouteApi.class, routeUrl, okHttpClient).getInstance();

完整源碼如下:


其中的 getInstance() 函數就是返回了需要被代理的接口對象;而其中的 ProxyInvocation 則是一個實現了 InvocationHandler 接口的類,這套代碼就是利用 JDK 實現動態代理的三板斧。

查看 ProxyInvocation 的源碼會發現當我們調用被代理接口的任意一個方法時,都會執行這裏的 invoke() 方法。

invoke() 方法自然就實現了上圖中提到的:編碼、遠程調用、解碼的過程;相信大家很容易看明白,由於不是本次探討的重點就不過多介紹了。

總結

其實理解這些就也就很容易看懂 Dubbo 這類 RPC 框架的核心源碼了,總體的思路也是類似的,只不過使用的私有協議,所以在編解碼時會有所不同。

所以大家要是想自己動手實現一個 RPC 框架,不妨參考這個思路試試,當用自己寫的代碼跑通一個 RPChelloworld 時的感覺是和自己整合了一個 DubboSpringCloud 這樣的第三方框架的感覺是完全不同的。

本文的所有源碼:

https://github.com/crossoverJie/cim

你的點贊與分享是對我最大的支持

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章