這是分析筆記的最後一篇,這篇介紹了p2p仿真中最常用的RPC機制在P2Psim中的實作。這篇對P2Psim的仿真機制的最後一部分進行了說明。P2Psim中,不同的P2P協定實作都是基于這個機制來模拟peer間的通訊。
RPC(Remote Procedure call)的本意是,一台電腦通過網絡來來執行另外一台電腦上的函數,函數執行的結果再送回本機。這個機制有很多實作和變形,比如xmlrpc, Soap, 我在這裡不扯開了,大家google一下就知道了。是以按照RPC的概念,P2P中peer之間的互相通路都可以看作是RPC操作。是以在P2P的仿真中,仿真軟體都不約而同實作一套簡化了的rpc接口,這樣在應用層的p2p協定隻要用這套接口就可以不必理會底層網絡通信的細節了。這篇中我給出了RPC實作的說明圖。
圖中,不同p2p協定通過調用Node中的doRPC()和asyncRPC()來發送資料給遠端的peer。前者是同步的,也就是說,在沒收到對方peer的回複或者逾時前,本peer就一直死等。後者是非同步的rpc調用。在非同步的方式下,peer調用asyncRPC()函數會立刻得到傳回,然後協定得到一個該次請求的句柄,可以了解成取貨憑證。然後peer隔一段時間在通過rcvRPC()函數,用這個句柄來查詢一下,這個遠端調用是不是傳回結果了,或者失敗了(比如網絡丢包)。這好比拿着取貨憑證去取貨一樣。同樣如果這個peer收到别人發送來的rpc請求,他也要提供處理相應請求的處理函數。當收到這個請求的時候,相應處理函數被調用。關于請求,我們遲點再分析。我們先逐個分析doRPC()和asyncRPC()的實作。
當Protocol類的對象調用了Node類中的doRPC()時,Node類首先通過_maktrunk函數把這個請求打包(為了更像一個網絡封包?不知道),然後依次調用_doRPC_send()函數在這個封包上面加一個channel(libtask裡面的多任務間的資料通信機制)把這個請求的trunk發給Network類的send()接口。Network根據拓撲算出這個封包到達對方peer的延遲,然後生成一個NetEvent事件放入事件隊列裡。當doRPC()發送了這個資料包後,立刻調用_doRPC_receve()來在這個封包的等待這個資料包上的channel上是否有資料過來,如果有,則從channel中取出這個rpc是否成功的資訊再依次傳回給doRPC()函數和上層的調用代碼。如果成功,這個rpc請求中的傳回值指針指向的資料結構已經被對方peer給改寫了。以這種方式模拟rpc結果資料的傳回。
當Protocol類的對象調用了Node類中的asyncRPC()接口的時候,機制稍微不同一點。asyncRPC同樣調用_maktrunk()封裝出一個trunk包,然後讓_doRPC_send()函數發送出這個包,但是傳回的rpc句柄(取貨憑證)被存放到_rpcmap結構中暫時儲存起來。然後asnycRPC()函數就立刻傳回這個句柄給上層protocol的調用代碼了。然後呢,上層代碼在之後的事件裡面可以時不時通過rcvRPC()接口來查詢一下_rpcmap結構裡面這個憑條對應的請求有沒有得到響應或者是否出錯了。
以上講完了rpc請求發送的基本邏輯流程,接下來說一下rpc請求被接收的流程。上篇我說了,當EventQueue處理NetEvent事件的時候調用其execute()會導緻Node中的Packet_handler()接口被調用。這個接口函數會區分,該消息對應的是rpc請求還是rpc應答。如果是應答的話,他就這個封包通過其channel(記得在_doRPC_send()中建立的channel麼?)發送過去。 如果_doRPC_receive()正在等待channel上的資料,這個資料就會讓_doRPC_receive()傳回,完成同步RPC。如果這是一個異步的rpc,無所謂,這個資料就存在channel裡面了,等peer調用rcvRPC()去查詢和收取。
如果這是一個請求事件,那Packet_handler()就建立一個新task來運作receive()函數。這個函數中,這個事件中rpc的請求類型會被拿出來分析,對應不同的事件類型,protocol裡面的不同僚件處理函數會被調用。也就是說Protocol對象執行個體中的相應RPC處理函數“被”執行了。根據執行結果,receive()函數構造出RPC響應資料包,然後再通過Network類的send()結構最終又變成NetEvent事件插入到事件隊列EventQueue裡面去了。至于RPC的響應如何處理,上一段已經說過了。
<a href="http://nathanxu.blog.51cto.com/attachment/200912/27/50836_1261905715qlf9.jpg"></a>
本文轉自nathanxu 51CTO部落格,原文連結:http://blog.51cto.com/nathanxu/250585,如需轉載請自行聯系原作者