一個簡單RPC框架是如何煉成的(III)——實現帶引數的RPC呼叫
阿新 • • 發佈:2018-10-31
上一篇,我們制定了一個很簡單的RPC訊息 的格式,但是還遺留了兩個問題
- 我們並沒有實現相應的encode和decode方法,沒有基於可以跨裝置的字串傳輸,而是直接的記憶體變數傳遞。
- 現在的RPC request不支援帶引數的請求命令。如add(a, b), 如何在RPC訊息中描述引數a,b 。
其實,也沒什麼太大不同。既然是要帶引數,那隻能擴充套件原來的Request訊息了,加個parameter成員,用於表示引數,具體的格式採用字典方式,{ ’arg1‘, arg1, 'arg2', arg2 ,....}。 這樣就可以解決多引數的表示問題。
class Request(object): ''' @RPC請求,包含命令id和請求內容兩部分。這個實現,與具體的RPC協議相關。 @這裡是簡化起見,採用python自身的字典作為其協議的資料結構 ''' def __init__(self): ''' Constructor ''' self.id = 0 #id的作用在於將Request和Response建立繫結關係.在非同步呼叫時就有用 self.command = None #sayHello self.parameter = {} def __str__(self): return ''.join(('id: ', str(self.id), ' command: ', str(self.command), ' parameter: ', str(self.parameter)))
add(a=1, b=2)的RPC 請求就是這個樣子了
Request : id = 3, command = 'add', parameter = {'a':1, 'b':2}
對應的,客戶端的add方法,我們可以這麼寫
def add(self, a, b):
req = Request()
req.id = 3
req.command = 'add'
req.parameter = {'a':a, 'b':b}
return self.request(req)
那麼服務端收到這個RPC請求後,怎麼處理得到引數呢?一個傳統而稍顯笨拙的方式是:
def add(self, a, b):
return a + b
def procReqeust__add(self, req):
parameter = req.parameter
a = parameter.get('a')
b = parameter.get('b')
return self.add(a, b)
這種方式的缺點就是沒辦法偷懶。(懶懶懶 ),每一個RPC呼叫,都要怎麼處理一下,煩死了,沒有任何技術含量的純苦力活,但還考驗細心,一不小心搞錯a或者b的名字了,呵呵,等著被請喝茶吧。
這時候,大殺器上場,指令碼語言就是找個好。總有你想不到的方便。直接上程式碼
def procReqeust__add(self, req):
parameter = req.parameter
return self.add(**parameter)
對上面**parameter不懂的同學自行度娘。這裡只是簡單解釋一下:**parmater的作用同那塊笨拙的程式碼一樣,但有一個前提條件,即使add宣告時,引數變數名a,b不能變。(c++同學可能暈了,竟然有語音有這樣的說法 )
至此,使用這種新的方式,我們server的程式碼就是這個樣子的,對沒有引數的方法,上面**也是可以放心使用的
def procRequest(self,req):
rsp = Response()
rsp.id = req.id
if req.command == 'sayHello':
rsp.result = self.sayHello(**req.parameter)
elif req.command == 'add':
rsp.result = self.add(**req.parameter)
else:
raise Exception("unknown command")
over,搞定,還挺滿意的