們講解 rpc 的訊息互動流程,目的是搞清楚乙個簡單的 rpc 方法呼叫背後究竟發生了怎樣複雜曲折的故事,以看透 rpc 的本質。
上圖是資訊系統互動模型巨集觀示意圖,rpc 的訊息互動則會深入到底層。
rpc 是兩個子系統之間進行的直接訊息互動,它使用作業系統提供的套接字來作為訊息的載體,以特定的訊息格式來定義訊息內容和邊界。
rpc 的客戶端通過檔案描述符的讀寫 api (read & write) 來訪問作業系統核心中的網路模組為當前套接字分配的傳送 (send buffer) 和接收 (recv buffer) 快取。
如上圖所示,左邊的客戶端程序寫 rpc 指令訊息到核心的傳送快取中,核心將傳送快取中的資料傳送到物理硬體 nic,也就是網路介面晶元 (network inte***ce circuit)。nic 負責將翻譯出來的模擬訊號通過網路硬體傳遞到伺服器硬體的 nic。伺服器的 nic 再將模擬訊號轉成位元組資料存放到核心為套接字分配的接收快取中,最終伺服器程序從接收快取中讀取資料即為源客戶端程序傳遞過來的 rpc 指令訊息。
訊息從使用者程序流向物理硬體,又從物理硬體流向使用者程序,中間還經過了一系列的路由網關節點。
上圖呈現的只是 rpc 一次訊息互動的上半場,下半場是乙個逆向的過程,從伺服器程序向客戶端程序返回響應資料。完整的一次 rpc 過程如下圖所示:
下面用 python **來描述上述過程。
# coding: utf-8
# server
import socket
sock = socket.socket(socket.af_inet, socket.sock_stream)
sock.bind(("localhost", 8080))
sock.listen(1) # 監聽客戶端連線
while true:
conn, addr = sock.accept() # 接收乙個客戶端連線
print conn.recv(1024) # 從接收緩衝讀訊息 recv buffer
conn.sendall("world") # 將響應傳送到傳送緩衝 send buffer
conn.close() # 關閉連線
# coding: utf-8
# client
import socket
sock = socket.socket(socket.af_inet, socket.sock_stream)
sock.connect(("localhost", 8080)) # 連線伺服器
sock.sendall("hello") # 將訊息輸出到傳送緩衝 send buffer
print sock.recv(1024) # 從接收緩衝 recv buffer 中讀響應
sock.close() # 關閉套接字
如果從上面**上觀察,我們其實很難看出上圖所示的複雜過程。浮現在多數人腦海中往往是下面的這幅簡約模型圖。相比之下它要簡單很多,這也正是作業系統設計的魅力所在,讓你時時刻刻都在使用它卻感受不到它的存在。
深入理解RPC 服務發現
先舉個例子,假如你要給一位以前從未合作過的同事發郵件請求幫助,但你卻沒有他的郵箱位址。這個時候你會怎麼辦呢?如果是我,我會選擇去看公司的企業 通訊錄 同理,為了高可用,在生產環境中服務提供方都是以集群的方式對外提供服務,集群裡面的這些 ip 隨時可能變化,我們也需要用一本 通訊錄 及時獲取到對應的服...
流程控制深入理解
概率的指導意義 不可能事件,必定事件,小概率事件 大概率事件 賭一把事件 設計過程 三維空間,一維時間,在某個時間點的三維空間下做出多個選擇語句,而執行階段,是把每個個體的時間全部給了空某個條選擇語句強制關聯的路徑下。解讀 是因為在某一點時間下 某個一小段或者還在考慮的時間範圍內 某個空間範圍內不清...
深入理解C語言 深入理解指標
關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...