跨語言的RPC


  1. 標准庫的RPC默認采用Go語言特有的Gob編碼,因此從其他語言調用Go語言實現的RPC服務將比較困難。在互聯網的微服務時代,每個RPC以及服務的使用者都可能采用不同的編程語言,因此跨語言是互聯網時代RPC的一個首要條件。得益於RPC的框架設計,Go語言的RPC其實也是很容易實現跨語言的。
  2. Go語言的RPC框架有兩個比較有特色的設計:一個是RPC數據打包時可以通過插件實現自定義的編碼和解碼;另一個是RPC建立在抽象的io.ReadWriteCloser接口之上,我們可以將RPC架設在不同的通信協議之上。這里我們嘗試通過官方自帶的net/rpc/jsonrpc拓展實現一個跨語言的RPC。
  3. 首先是基於JSO你編碼重新實現RPC服務:

    代碼中最大的變化是用rpc.ServeCodec()函數替代了rpc.ServeConn()函數,傳入的參數是針對服務器端的JSON編解碼器。
  4. 然后是實現JSON版本的客戶端:

    先手工調用了net.Dial()函數建立了TCP鏈接,然后基於該鏈接建立針對客戶端的JSON編解碼器。
  5. 在確保客戶端可以正常調用RPC服務的方法之后,我們用一個普通的TCP服務來代替GO語言版的RPC服務,這樣可以查看客戶端調用時發送的數據格式。例如,通過命令nc -l 1234在同樣的端口啟動一個TCP服務。然后執行一個RPC調用會發現nc輸出了一下的信息:
    {"method":"HelloService.Hello", "params":["hello"], "id":0}
    這是一個JSON編碼的數據,其中method部分對應要調用的由RPC服務和方法組合成的名字,params部分的第一個元素為參數,id是由調用方維護的唯一的調用編號。
  6. 請求的JSON數據對象在內部對應兩個結構體:客戶端是clientRequest,服務器端是serverRequest。clientRequest和serverRequest結構體的內容基本是一致的。


    在獲取到RPC調用對應的JSON數據后,可以通過直接向架設了RPC服務的TCP服務器發送JSON數據模擬RPC方法調用:
    $ echo -e '{"method":"HelloService.Hello", "params":["hello"], "id":1}' | nc localhost 1234
    返回的結果也是JSON格式的數據:
    {"id":1, "result":"hello:hello", "error":null}
    其中id對應輸入的id參數,result為返回的結果,error部分在出問題時表示錯誤信息。對順序調用來說,id不是必須的。但Go語言的RPC框架支持異步調用,當返回結果的順序和調用的順序不一致時,可以通過id來識別對應的調用。
  7. 返回的JSON數據也對應內部的兩個結構體:客戶端是clientResponse,服務器端是serverResponse。兩個結構體的內容同樣也是類似的:

  8. 因此,無論采用哪種語言,只要遵循同樣的JSON結構,以同樣的流程就可以和Go語言編寫的RPC服務進行通信。這樣就實現了跨語言的RPC。
    6和7中的結構體在net/rpc/jsonrpc/client.go和net/rpc/jsonrpc/server.go中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM