天天看點

實作一個迷你版的RPC前言動手實作RPC

在實際背景服務開發中,比如訂單服務(開發者A負責)需要調用商品服務(開發者B負責),那麼開發者B會和A約定調用API,以接口的形式提供給A。通常都是B把API上傳到Maven私服,然後B開始寫API的實作,A隻需要引入API依賴進行開發即可。

實作一個迷你版的RPC前言動手實作RPC
實作一個迷你版的RPC前言動手實作RPC
注意,我将商品服務的API以及實作分為Maven的2個子產品來開發。這裡,我們想給定一個商品ID,查詢得到商品對象資訊。
實作一個迷你版的RPC前言動手實作RPC
實作一個迷你版的RPC前言動手實作RPC
要注意的是,Product是可以被序列化的,Why? 很顯然,訂單系統調用商品系統的時候,需要商品系統傳回一個商品,必然涉及到發生網絡傳輸,這就涉及對象的序列化和反序列化了。
實作一個迷你版的RPC前言動手實作RPC
實作一個迷你版的RPC前言動手實作RPC
在訂單系統工程中需要引入商品服務API依賴。 在上圖代碼中,最重要的就是rpc方法了!
實作一個迷你版的RPC前言動手實作RPC
第一,我們看到了Proxy.newProxyInstance,很顯然在進行動态代理。也即是說,在訂單服務調用商品服務的代碼中,我們先是通過動态代理傳回一個代理的IProductService類型對象,這意味着當代理對象調用queryById方法的時候,會自動調用invoke方法! 第二,我們看看invoke到底做了些什麼? 它本質上就是進行Socket通信,那麼它需要傳遞什麼資訊給到商品服務呢? 我們知道訂單系統就是想調用商品服務的某個類的某個方法,然後把這個方法的傳回結果傳輸給訂單系統! 想一想,如何調用某個類的某個方法呢? 隻要我們能确定這個類的全限定類名、确定方法名、确定方法的參數類型,給定方法需要的具體參數,通過反射就能實作。 商品服務調用後得到的結果,我們序列化寫入Socket流中,在訂單系統中反序列化得到對象即可。 第三,這裡需要思考一個問題:在訂單系統中我們隻知道商品服務的API,并不知道這背後的API到底是如何實作的,是以我們需要有一個映射,就是商品服務的API到商品服務的實作的一個映射關系,其實這就是所謂的服務的注冊!
實作一個迷你版的RPC前言動手實作RPC
實作一個迷你版的RPC前言動手實作RPC
實作一個迷你版的RPC前言動手實作RPC
從這裡,可以清晰的看到,商品服務讀取了訂單系統調用商品系統時發送的資料,利用反射機制,進行方法調用,并把調用結果寫入Socket輸出流。
實作一個迷你版的RPC前言動手實作RPC
啟動商品服務後,通過訂單系統發起對商品服務的調用。

以前總認為RPC是遙不可及的,感覺是個很神奇的東西,實際上它的底層實作不就是這樣的麼~