子產品越來越多,業務越來越複雜,RPC 就上場了,在 PHP 的世界裡,鳥哥的作品一直備受廣大網友的青睐。下面一起學習下鳥哥的 PRC 架構 Yar 。
RPC 采用用戶端/伺服器模式。首先,客戶機調用程序發送一個有程序參數的調用資訊到服務程序,然後等待應答資訊。在伺服器端,程序保持睡眠狀态直到調用資訊的到達為止。當一個調用資訊到達,伺服器獲得程序參數,計算結果,發送答複資訊,然後等待下一個調用資訊,最後,用戶端調用程序接收答複資訊,獲得程序結果,然後調用執行繼續進行。
這和我們外網 api 的原理不都一個樣麼?那麼我們一起看看高大上的 Yar 是怎麼在玩。
用戶端代碼,假設該服務設在區域網路<code>10.211.55.4</code>上
伺服器端代碼
通路結果如下
實際呢,yar client 是通過<code>__call</code>這個魔術方法來實作遠端調用的,在Yar_client類裡面并沒有任何方法,當我們在調用一個不存在的方式的時候,就會執行<code>__call</code>方法,這個在架構中非常常見。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLlBTYjlzMyIGM0gDOiVDMzAzM0IWYyMWZzEGO3QWZjRWOhFGM1gjN28CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
在 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>
整理了整體的執行流程如下圖
鳥哥在<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 版本的用戶端,這樣總算有所收獲,這份代碼也和我們平常寫的業務邏輯還是有些差別,二進制的東西居多,整個過程下來對網絡資料的傳輸有了更深刻的了解和學習哈。