rpc框架yar之源碼解析- 入門和原理介紹

關於rpc的文章,網上的內容很多,但我還是準備寫一下,主要是自己的理解吧。算是公衆號的第一篇技術類文章吧。

上週給團隊小夥伴分享了也是下面基礎入門的內容,本文主要結合一個簡單框架yar的原理和源碼來說明詳細情況。


RPC的定義

RPC,即 Remote Procedure Call(遠程過程調用),調用遠程計算機上的服務,就像調用本地服務一樣。

RPC可以很好的解耦系統,如WebService就是一種基於Http協議的RPC。


RPC的框架

各種架構都是在一定環境背景下產生的,有跨語言的,java語言的,有php的,有基於http的,有基於http2的。如下:

Thrift, gRPC, rpcx, motan, dubbox

Phprpc, yar, swoole, Hprose 


RPC調用

image.png

這裏以dubbo的架構圖爲例,dubbo主要分成4個角色:消費者(Consumer),生產者(Provider),監控中心(Monitor),註冊中心(Registry)。

Provider: 暴露服務的服務提供方,生產者。 
Consumer: 調用遠程服務的服務消費方。 
Registry: 服務註冊與發現的註冊中心。 
Monitor: 統計服務的調用次數和調用時間的監控中心。


調用方法如下:

0. 服務容器啓動,加載,運行服務提供者(server端)。 
1.服務提供者在啓動時,向註冊中心註冊自己提供的服務。 
2.服務消費者在啓動時,向註冊中心訂閱自己所需的服務。 
3.註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。 
4.服務消費者,從提供者地址列表中,根據指定的負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用。 
5.服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。


以上是從網上其他帖子上找的調用內容。基本上涵蓋了rpc框架的基本思路,monitor和registry不是必須的,如果有其他方式替代, 也可省略或者換成其他可以實現功能的方式,如集中處理日誌。下面是我們在實際使用中用到的內容。


業務背景:在DAU超過1億的微博,微博基礎數據獨立成平臺,這樣返回的PC,手機,H5其實是基礎數據,要想被手機端所用,實際上需要加工然後傳到端上展示。而爲了統一化管理,網頁版和手機app版儘量使用同一套解析。業務需求產生,在一定的歷史背景下,產生了rpc的調用模式。條條大路通羅馬,問題不止一個解決方案,我們只是採用了一種,即結合http,nginx ,php-fpm等使用yar這個php擴展模塊實現這個業務。


嚴格意義上講yar不能獨立使用的,沒有dubbo,motan等那種自己獨立成框架體系。有些部分交給使用者自己實現,如日誌記錄,我們的日誌記錄實際與yar關係不大。框架數據傳輸方式還是藉助http,結合nginx,php-fpm等內容,基礎還是個http的請求。(curl和sockert兩種方式,sockert目前我們沒有使用)。沒有註冊發現服務的具體使用,這個完全由lvs給我們解決,服務的可用完全交給了運維。


瞭解了各個角色,我們來看下核心內容,Yar實現了rpc的基礎部分,即數據的譯碼/解碼和傳輸,我感覺這兩部分是這個框架的核心。下面是流程圖:

image.png


請求過程:

Client需要遠程調用的時候,先初始化數據,數據主要包括三個部分header, packager_name,request_body,然後根據配置中的方式從pack_list選擇合適的序列化方式(msgpack,json,php)

對request_body進行序列化。 然後進行傳輸,傳輸方式 同樣是採用工廠方法,從已有的方式中選擇Curl/sockert方式進行傳輸數據,傳輸數據的過程實際就是發送一個http請求(我們以curl爲例)。

服務器端監聽端口,底層網絡實現都利用現有的nginx, php-fpm。在PHP代碼中,實現的地方實例化一個類,然後根據request的內容,解析body,然後去初始化header, 獲得packager_name,根據packer_name解析yar_body的內容。


以下是每次request和response的數據情況。以request爲例傳輸的body數據包含三個部分,82byte的頭部,packager_name,和經過packager_name序列化的string。當這段數據傳到server端,按照固定的結構解析出來即可。


image.png

PACK過程是對數據作如下處理的過程。以msgpack爲例,對中間部分的數據進行序列化。生成最右邊的內容(序列化後的字符串有最右有差別,這裏只是拿json舉例)。

image.png


傳輸

yar目前有兩種傳輸方式,這個在之前提到過curl和socket方式。因爲socket實際沒有用過所以這裏主要介紹curl。

curl的模塊主要以來底層的CURL模塊,主要封裝瞭如下方法。其中multi系列主要是解決並行請求的方案。

image.png

php_yar_curl_open

這個方法主要是用CURL創建一個連接對象。這裏有個複用的機制,當options & 

YAR_PROTOCOL_PERSISTENT(0x1) 爲true的時候,會去已經使用的連接中找一下,如果存在並且沒有在用則複用。


php_yar_curl_send

這個函數主要是把request需要的數據,轉成字符串,然後放在請求的postfield裏面。


php_yar_curl_exec

將postfield內容,通過http請求發送出去。獲得返回的內容。然後按照上述內容解析出結果。


本來還想分享grpc的protobuf和htt2,鑑於粗淺學習階段,網上的其他博客文章更詳細,這裏就不寫了,等我實際有自己的理解再說啦。


凡事都沒有完美,也碰到過yar的不足之處,比如server的handle方法,解析post數據,執行對應的方法返回都在這裏了。沒有將請求的實際方法暴露,這樣在server端統計起來比較困難。曾試圖在源碼中加個getCallMethod方法去標記這個內容,不過只是自己玩玩,沒有實際應用...


有同學問我爲啥我們當時要用yar,也許別的框架也能滿足我們的需求,一定的歷史背景決定一定的技術架構。技術的選型更多傾向於開發者的水平----即選擇自己駕馭的技術,站在巨人的肩膀上展望遠處。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章