一個簡單RPC框架是如何煉成的(II)——制定RPC消息

開局篇我們說了,RPC框架的四個核心內容

  1. RPC數據的傳輸
  2. RPC消息 協議
  3. RPC服務註冊
  4. RPC消息處理
下面,我們先看一個普通的過程調用
class Client(object):
    
    def __init__(self):
        self.remote = None
    
    ##
    # 內部是委託給遠程remote對象來獲取結果。
    def sayHello(self):
        if self.remote: return self.remote.sayHello()
        else : return None
    
class Server(object):
    
    def __init__(self):
        pass
    
    def sayHello(self):
        return 'Hello World'    


if __name__ == '__main__':
    server = Server()
    client = Client()
    client.remote = server
    print(client.sayHello())

這是一個常見的過程調用的例子,client調用sayHello,實際委託給Server的sayHello方法來實現。但他不是RPC調用,因爲起碼不是遠程的,另外,也沒有我們提到的四個核心內容。於是我們的任務就是通過一點點的代碼修改,爲其引入RPC框架。
第一步,訂協議。俗話說得好,沒有規矩不成方圓。
還是繼續能多簡單就多簡單。
RPC請求:Request, 包含一個請求id 和 一個請求命令,如‘sayHello'
class Request(object):
    '''
    @RPC請求,包含命令id和請求內容兩部分。這個實現,與具體的RPC協議相關。
    @這裏是簡化起見,採用python自身的字典作爲其協議的數據結構
    '''


    def __init__(self):
        '''
        Constructor
        '''
        self.id = 0 #id的作用在於將Request和Response建立綁定關係.在異步調用時就有用
        self.command = None #sayHello
        
    def __str__(self):
        return ''.join(('id: ', str(self.id),  '   command: ', str(self.command)))

同樣的,對RPC Response,也定義如下
class Response(object):
    '''
    @RPC回覆。 包含答覆id和執行結果兩部分內容。其中答覆id與對應的請求id一致。
    @簡單起見,協議的實現使用python自家的字典
    '''


    def __init__(self):
        '''
        Constructor
        '''
        self.id = 0
        self.result = None
    
    def __str__(self):
        return ''.join(('id: ', str(self.id),  '   result: ', str(self.result)))

定義好協議之後,我就對Client稍作修改,將原來直接的接口調用 self.remote.sayHello更改爲 send Request (command='sayHello')
    def sayHello(self):
        req = Request() // 構建一個RPC請求消息
        req.id = 1
        req.command = 'sayHello'
        return self.request(req)
  
    def request(self, req):
        rsp = self.remote.procRequest(req) // 將請求消息發送給遠程服務端。但因爲傳輸層這裏還沒實現,所以先暫時還是直接調用遠端接口
        return rsp.result

然後,服務端也要相應修改,需要根據request請求中的command命令,調用具體的方法,並將執行結果封裝到Response中,返回給客戶端。
def procRequest(self,req):
        rsp = Response()
        rsp.id = req.id   
        if req.command == 'sayHello':
            rsp.result = self.sayHello()
        else:
            raise Exception("unknown command")
        
        return rsp

到這裏,RPC框架中的RPC消息已經初具雛形,不過
  • 我們並沒有實現相應的encode和decode方法,沒有基於可以跨設備的字符串傳輸,而是直接的內存變量傳遞。
  • 現在的RPC request不支持帶參數的請求命令。如add(a, b), 如何在RPC消息中描述參數a,b 。
這些問題我們在後面還會繼續展開處理



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