一個簡單RPC框架是怎樣煉成的(V)——引入傳輸層

技術mix呢發表於2017-11-07

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

  1. RPC資料的傳輸

  2. RPC訊息 協議
  3. RPC服務註冊
  4. RPC訊息處理   
接下來處理傳輸資料。實際應用場景一般都是基於socket。socket程式碼比較多,使用起來也比較麻煩。

並且詳細的傳輸通道使用socket或者其它的方式,如更上層的http,或者android裡的binder,都是可替換的。僅僅是詳細的一種實現而已。所以,這裡我就偷個懶,僅僅是引入一個非常easy的Connection類。用來描寫敘述一下怎樣將傳輸資料 這一層給獨立出來。


首先簡單列出Connection類的實現,非常easy,就是兩個list。一個管傳送。一個管接收。

(實現沒有考慮多執行緒安全。實際是必須考慮的)。

須要說明的是,這裡的recv的實現約定是堵塞式的,也就是假設沒有收到不論什麼資料。recv呼叫會一直堵塞。

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去接收。


接著改動client的request請求,不再直接呼叫server端的procRequest方法,而是將請求交給connection,去傳送。

 然後等待connection收到server端的回覆,將回復訊息從connection中取出來。

def request(self, req):
        # 所有簡化處理。不考慮執行緒安全問題,不考慮非同步
        # 先是將RPC訊息傳送到服務端,然後服務端就會處理,並將結果發回到client,client這邊接收處理結果。
        # 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。

興許假設有時間,會再進行完好






本文轉自mfrbuaa部落格園部落格,原文連結:http://www.cnblogs.com/mfrbuaa/p/5386763.html,如需轉載請自行聯絡原作者


相關文章