天天看點

我與鳥哥 Yar 的親密接觸揭開 Yar 神秘面紗

子產品越來越多,業務越來越複雜,RPC 就上場了,在 PHP 的世界裡,鳥哥的作品一直備受廣大網友的青睐。下面一起學習下鳥哥的 PRC 架構 Yar 。

RPC 采用用戶端/伺服器模式。首先,客戶機調用程序發送一個有程序參數的調用資訊到服務程序,然後等待應答資訊。在伺服器端,程序保持睡眠狀态直到調用資訊的到達為止。當一個調用資訊到達,伺服器獲得程序參數,計算結果,發送答複資訊,然後等待下一個調用資訊,最後,用戶端調用程序接收答複資訊,獲得程序結果,然後調用執行繼續進行。

這和我們外網 api 的原理不都一個樣麼?那麼我們一起看看高大上的 Yar 是怎麼在玩。

用戶端代碼,假設該服務設在區域網路<code>10.211.55.4</code>上

伺服器端代碼

通路結果如下

實際呢,yar client 是通過<code>__call</code>這個魔術方法來實作遠端調用的,在Yar_client類裡面并沒有任何方法,當我們在調用一個不存在的方式的時候,就會執行<code>__call</code>方法,這個在架構中非常常見。

我與鳥哥 Yar 的親密接觸揭開 Yar 神秘面紗

在 yar 中規定的傳輸協定如下圖所示,請求體為82個位元組的<code>yar_header_t</code>和8位元組的打包名稱和請求實體<code>yar_request_t</code>,在<code>yar_header_t</code>裡面用<code>body_len</code>記錄8位元組的打包名稱+請求實體的長度;傳回體類似,隻是實體内容的結構體稍微不同,在<code>reval</code>裡面才是實際最後用戶端需要的結果。

整個傳輸以二進制流的形式傳送。

在<code>yar_transport.h</code>中,定義了<code>yar_transport_t</code>結構體,先不考慮并行處理的接口,以<code>socket</code>傳輸協定為例子學習,代碼簡化一些如下:

然後在<code>transports/socket.c</code>中定義了<code>yar_transport_socket</code>

整理了整體的執行流程如下圖

我與鳥哥 Yar 的親密接觸揭開 Yar 神秘面紗

鳥哥在<code>yar_packager.c</code>中首先定義了一個結構體,初始化的時候會把各個<code>yar_packager_t</code>注冊到<code>**packagers</code>數組中。

然後通過傳入的<code>name</code>和<code>yar_packager_t</code>的<code>name</code>做比較,相同則傳回該執行個體

親密接觸完畢。紙上得來終覺淺,絕知此事要躬行。這篇部落格隻能是輔助大家在看源碼時一起分析,覺得不能抛開源碼僅僅看這篇部落格。

怎麼樣才能對這個内容真正的掌握呢,是以我有折騰了一個Java 版本的用戶端,這樣總算有所收獲,這份代碼也和我們平常寫的業務邏輯還是有些差別,二進制的東西居多,整個過程下來對網絡資料的傳輸有了更深刻的了解和學習哈。