開局篇我們說了,RPC框架的四個核心內容
- RPC數據的傳輸。
- RPC消息 協議
- RPC服務註冊
- 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 。
這些問題我們在後面還會繼續展開處理