RPC (Remote Procedure Call)即遠程過程調用,是分佈式系統常見的一種通訊方法,已經有 40 多年曆史。當兩個物理分離的子系統須要創建邏輯上的關聯時,RPC 是牽線搭橋的常見技術手段之一。除 RPC 以外,常見的多系統數據交互方案還有分佈式消息隊列、HTTP 請求調用、數據庫和分佈式緩存等。nginx
其中 RPC 和 HTTP 調用是沒有通過中間件的,它們是端到端系統的直接數據交互。HTTP 調用其實也能夠當作是一種特殊的 RPC,只不過傳統意義上的 RPC 是指長鏈接數據交互,而 HTTP 通常是指即用即走的短連接。git
RPC 在咱們熟知的各類中間件中都有它的身影。Nginx/Redis/MySQL/Dubbo/Hadoop/Spark/Tensorflow 等重量級開源產品都是在 RPC 技術的基礎上構建出來的,咱們這裏說的 RPC 指的是廣義的 RPC,也就是分佈式系統的通訊技術。RPC 在技術中的地位比如咱們身邊的空氣,它無處不在,可是又有不少人根本不知道它的存在。github
本地過程調用數據庫
RPC就是要像調用本地的函數同樣去調遠程函數。在研究RPC前,咱們先看看本地調用是怎麼調的。假設咱們要調用函數Multiply來計算lvalue * rvalue的結果:緩存
1 int Multiply(int l, int r) { 2 int y = l * r; 3 return y; 4 } 5 6 int lvalue = 10; 7 int rvalue = 20; 8 int l_times_r = Multiply(lvalue, rvalue);
那麼在第8行時,咱們實際上執行了如下操做:服務器
以上5步就是執行本地調用的過程。(20190116注:以上步驟只是爲了說明原理。事實上編譯器常常會作優化,對於參數和返回值少的狀況會直接將其存放在寄存器,而不須要壓棧彈棧的過程,甚至都不須要調用call,而直接作inline操做。僅就原理來講,這5步是沒有問題的。)網絡
遠程過程調用帶來的新問題框架
在遠程調用時,咱們須要執行的函數體是在遠程的機器上的,也就是說,Multiply是在另外一個進程中執行的。這就帶來了幾個新問題:socket
因此,要實現一個RPC框架,其實只須要把以上三點實現了就基本完成了。分佈式
Call ID映射能夠直接使用函數字符串,也可使用整數ID。映射表通常就是一個哈希表。
序列化反序列化能夠本身寫,也可使用Protobuf或者FlatBuffers之類的。
網絡傳輸庫能夠本身寫socket,或者用asio,ZeroMQ,Netty之類。
最後,有興趣的能夠看咱們本身寫的一個小而精的RPC庫 tinyrpc(hjk41/tinyrpc),對於理解RPC如何工做頗有好處。
---------------------------------------------------------------------------------------------------------------
SOA的發展
咱們在作一個訪問量不大的項目的時候,一臺服務器部署上一個應用+數據庫也就夠了.
那麼訪問量稍微大一點以後呢,爲了解決用戶反饋的卡,反應慢的狀況,咱們就上集羣.架設nginx,部署多個服務,由nginx負責把請求轉發到其餘服務上,這樣就解決了用戶說的卡慢問題.
過了一段時間以後呢,咱們發現數據庫已經扛不住了,應用服務無缺,數據庫有時候宕機. 那這個時候呢,咱們就上數據庫讀寫分離,再架設幾臺數據庫服務器,作主從,作分庫分表. 而後數據庫也不宕機了,服務又恢復了流暢.
又過了一段時間,公司事業增增日上,服務訪問量愈來愈高,且大部分都是查詢, 吸收以前宕機且爲了辦證數據庫的健壯性,咱們這個時候又加上了緩存, 把用戶高頻次訪問的數據放到緩存裏.
後來,項目功能愈來愈多,整個項目也愈發龐大,修改一個類就須要全盤上傳,切換nginx重啓,這樣的發佈流程愈來愈長,愈來愈繁雜.而後咱們開始把模塊拆分,用戶信息分個項目,訂單系統分一個項目.這樣就達到了,用戶模塊代碼修改的時候,只須要更新用戶信息服務就行了.可是仍是須要切換頂層的nginx.把要重啓的服務的流量切到可用服務上. 這個時候咱們就想到了RPC
那麼RPC解決了什麼呢? 全部的服務在啓動的時候註冊到一個註冊機裏面,而後頂層處理在接收到nginx的請求時,去註冊機找一個可用的服務,並調用接口. 這樣子呢,在不加新功能的時候,頂層處理服務咱們就不須要動了? 那修改了用戶信息項目的時候,咱們只須要一個個更新用戶信息項目的服務羣就行了?
這樣的話,不管是擴展仍是服務的健壯性都妥妥的了