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

之前我們制定了一個很簡單的RPC消息 的格式,但是還遺留了兩個問題,上一篇解決掉了一個,還留下一個

  • 我們並沒有實現相應的encode和decode方法,沒有基於可以跨設備的字符串傳輸,而是直接的內存變量傳遞。
  • 現在的RPC request不支持帶參數的請求命令。如add(a, b), 如何在RPC消息中描述參數a,b 。
下面我們處理掉這個編解碼問題。
實際的RPC應用基本都是跨機器連接,所以無法直接傳遞內存變量,也就是說還需要將消息編碼成 諸如字符串一類的可以跨設備傳輸的內容。具體的RPC消息的封裝協議很多,常見的是基於xml,json封裝的。但如果抽象一下,實際也就是一個編解碼,管你編碼成什麼內容呢,就是不編碼也可以。管他黑貓白貓,只要能傳過去,就是好貓。
這裏我還是簡單原則,重點在於曉義嘛。利用python裏的兩個運算。 str 和eval。
假設 一個字典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的代碼也要稍作調整,那個很簡單,調用一下上面的 方法就可以了,這裏不貼了。
over,RPC消息 這一塊,我們徹底玩完了。
總結:
  • Request和Resonse的定義可以一直不變,
  • encode 和decode方法,如孫大聖,是可以千變萬化的。如果採用xml或者json或者其他的描述,只要自定義encode和decode方法即可
  • 從更高的層次看,RPC消息,其實就是對函數調用的一個描述,所以充其量就是view。既然是view,實際自由度是很大的。

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