一個簡單RPC框架是怎樣煉成的(IV)——實現RPC消息的編解碼

以前咱們制定了一個很是easy的RPC消息 的格式,但是還遺留了兩個問題,上一篇解決掉了一個。還留下一個python

  • 咱們並無實現對應的encode和decode方法,沒有基於可以跨設備的字符串傳輸,而是直接的內存變量傳遞。
  • 現在的RPC request不支持帶參數的請求命令。

    如add(a, b), 怎樣在RPC消息中描寫敘述參數a,b 。json

如下咱們處理掉這個編解碼問題。
實際的RPC應用基本都是跨機器鏈接。因此沒法直接傳遞內存變量,也就是說還需要將消息編碼成 諸如字符串一類的可以跨設備傳輸的內容。

詳細的RPC消息的封裝協議很是多。常見的是基於xml,json封裝的。但假設抽象一下,實際也就是一個編解碼,管你編碼成什麼內容呢。就是不編碼也可以。管他黑貓白貓。僅僅要能傳過去,就是好貓。
函數

這裏我仍是簡單原則,重點在於曉義嘛。

利用python裏的兩個運算。編碼

str 和eval。spa

若是 一個字典msg =  { 'a' : 1, 'b' : 2}.  那麼str(msg) =   " { 'a' : 1, 'b' : 2}", 注意變成字符串嘍。

        而後eval(" { 'a' : 1, 'b' : 2}")-->msg, 作一個eval運算,又從字符串變成 字典變量了。

 

       因而編碼時。先將RPC消息轉換成dict,而後調用str編碼成字符串。

         解碼時。先調用eval 獲得dict對象,而後再轉換爲詳細的RPC消息對象

設計已定,剩下的就僅僅是code filling。
先改動一下原來Request的str方法。返回一個dict的字符串表示。對Response也作相似處理
class Request(object):
    def __str__(self):
        return str({'id':self.id,  'command':self.command, 'parameter':self.parameter})

而後引入encode方法
    @classmethod
    def encode(cls, message):
        if isinstance(message, Request):
            return str(message)
        elif isinstance(message, Response):
            return str(message)
        elif isinstance(message, Notification):
            return str(message)
        else:
            raise Exception('unknown type when encode')

相同的,引入decode方法,略微複雜一些。基本的麻煩在於怎樣區分解碼出來的是Response仍是Request
個人辦法是比較投機的,直接依據字典的內容去推斷。有command字段的確定是request,有result字段的確定是response
@classmethod    
    def decode(cls, data):
        info = eval(data)
        if 'command' in info:
            request = Request()
            request.id = info.get('id')
            request.command = info.get('command') 
            request.parameter = info.get('parameter', {})
            return request
        elif 'result' in info:
            response = Response()
            response.id = info.get('id')
            response.result = info.get('result')
            return response
        elif 'message' in info:
            note = Notification()
            note.message = info.get('message')
            return note
        else:
            raise Exception('unknown data when decode')

另外,client和server的代碼也要稍做調整,那個很是easy,調用一下上面的 方法就可以了。這裏不貼了。
over,RPC消息 這一塊,咱們完全玩完了。
總結:
  • Request和Resonse的定義可以一直不變。
  • encode 和decode方法,如孫大聖。是可以變幻無窮的。假設採用xml或者json或者其它的描寫敘述,僅僅要本身定義encode和decode方法就能夠
  • 從更高的層次看,RPC消息,事實上就是對函數調用的一個描寫敘述,因此充其量就是view。既然是view。實際自由度是很是大的。
相關文章
相關標籤/搜索