動態代理與RPC

前言


隨着最近關注 cim 項目的人愈加增多,致使提的問題以及 Bug 也在增長,在修復問題的過程當中不免代碼潔癖又上來了。java

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

先後對比

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

簡單來講就是一個 IM 即時通信系統,主要有如下部分組成:api

  • 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 包,服務消費者只須要依賴這個包就能夠實現接口調用。spa

固然最終使用的是 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

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

相關文章
相關標籤/搜索