一個簡單RPC框架是如何煉成的(V)——引入傳輸層
阿新 • • 發佈:2018-10-31
開局篇我們說了,RPC框架的四個核心內容
- RPC資料的傳輸。
- RPC訊息 協議
- RPC服務註冊
- RPC訊息處理
首先簡單列出Connection類的實現,很簡單,就是兩個list,一個管傳送,一個管接收。(實現沒有考慮多執行緒安全,實際是必須考慮的)。
class Connection(object): ''' @RPC 連線。一般說來,都是socket連線,這裡簡化起見,直接本地變數實現。 ''' def __init__(self, sending_msg_list, recving_msg_list): ''' Constructor ''' self.sending_msg_list = sending_msg_list self.recving_msg_list = recving_msg_list def send(self, message): self.sending_msg_list.append(message) def recv(self): while len(self.recving_msg_list) == 0: time.sleep(0.01) return self.recving_msg_list.pop(0) def isClosed(self): return False
有了這個connection,剩下的就只要將rpc訊息統統通過這個connection去傳送,通過這個Connection去接收。
接著修改客戶端的request請求,不再直接呼叫server端的procRequest方法,而是將請求交給connection,去傳送。 然後等待connection收到server端的回覆,將回復訊息從connection中取出來。
def request(self, req): # 全部簡化處理,不考慮執行緒安全問題,不考慮非同步 # 先是將RPC訊息傳送到服務端,然後服務端就會處理,並將結果發回到客戶端,客戶端這邊接收處理結果。 # self.remote.procRequest(req) // 刪除 self.conn.send(req) rsp = self.conn.recv() return rsp.result
同樣的,修改服務端收到request請求後的處理。首先反覆呼叫connection.recv()方法讀取客戶端發過來的請求。當請求處理完成後,不再直接以函式返回的方式return,而是將rsp交給connection,由connection負責傳輸給client
# def procRequest(self, req): 調整引數列表,不再需要req
def procRequest(self):
# 迴圈讀取並處理收到的客戶端請求
while True:
req = self.conn.recv()
rsp = Response()
rsp.id = req.id
if req.command == 'sayHello':
rsp.result = self.sayHello()
elif req.command == 'whoAreYou':
rsp.result = self.whoAreYou()
else:
raise Exception("unknown command")
# return rsp # rsp也是通過connection最終傳給client,而不是直接函式返回
self.conn.send(rsp)
最後,列一下connection的初始化
slist = []
rlist = []
client = Client(Connection(slist, rlist))
server = Server(Connection(rlist, slist))
server.start()
總結,引入傳輸層的意義在於 1. 實現client與server端的解耦,client端不再需要持有server端的物件了。 這也是實現“遠端呼叫 ”所必須的。 2. 傳輸層的實現有很大的自由度,一般說來,他無需關心具體的RPC訊息的格式,只需要完成資料的可靠傳輸就可以了。 3. 傳輸層具體基於socket,binder, 是採用http,udp,tcp這些都是自由的,根據需要選擇就可以了。也就是相當於一個可以自由拼接的元件。 4. 上面的模型實在過於簡單,沒有考慮多執行緒保護,沒有考慮異常。實際比較理想的情況,應該起碼有個類,Connector,以及Channel。其中channel只負責資料的傳輸,Connector負責管理channel。 後續如果有時間,會再進行完善