<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                Yar 是一個輕量級, 高效的[RPC](https://developer.51cto.com/art/201906/597963.htm)(是遠程過程調用(Remote Procedure Call)的縮寫形式)框架, 它提供了一種簡單方法來讓PHP項目之間可以互相遠程調用對方的本地方法. 并且Yar也提供了并行調用的能力. 可以支持同時調用多個遠程服務的方法 是[Laruence大佬](https://www.laruence.com/2020/03/16/5578.html)還在微博的時候為了優化微博的性能而開發的一個工具,Yar的并行調用在微博被大量應用以降低用戶請求耗時 ## 需求 如果需要使用Msgpack作為打包協議, 則需要在configure的時候加上--enable-msgpack, 并且要保證Msgpack擴展也安裝到PHP內. [?https://pecl.php.net/package/yar](https://pecl.php.net/package/yar) * [預定義常量](https://www.php.net/manual/en/yar.constants.php) * [例子](https://www.php.net/manual/en/yar.examples.php) * [Yar\_Server](https://www.php.net/manual/en/class.yar-server.php)— Yar\_Server類 * [Yar\_Server :: \_\_ construct](https://www.php.net/manual/en/yar-server.construct.php)—創建一個HTTP RPC 服務器 * [Yar\_Server :: handle](https://www.php.net/manual/en/yar-server.handle.php)—啟動RPC服務器 <br> * [Yar\_Client](https://www.php.net/manual/en/class.yar-client.php)— Yar\_Client類 * [Yar\_Client :: \_\_ call](https://www.php.net/manual/en/yar-client.call.php)(string`$method`,array`$parameters`) :void—調用遠程服務 * [Yar\_Client :: \_\_ construct](https://www.php.net/manual/en/yar-client.construct.php)(string`$url`\[,array`$options`\] )—創建一個客戶端實例 * [Yar\_Client :: setOpt](https://www.php.net/manual/en/yar-client.setopt.php)(int`$name`,[mixed](https://www.php.net/manual/en/language.pseudo-types.php#language.types.mixed)`$value`) :[Yar\_Client](https://www.php.net/manual/en/class.yar-client.php)—設置調用的配置 <br> * [Yar\_Concurrent\_Client](https://www.php.net/manual/en/class.yar-concurrent-client.php)— Yar\_Concurrent\_Client類 * [Yar\_Concurrent\_Client :: call](https://www.php.net/manual/en/yar-concurrent-client.call.php)(string`$uri`,string`$method`\[,array`$parameters`\[,[callable](https://www.php.net/manual/en/language.types.callable.php)`$callback`\[,[callable](https://www.php.net/manual/en/language.types.callable.php)`$error_callback`\[,array`$options`\]\]\]\] ) :int—注冊一個并行的服務調用 * [Yar\_Concurrent\_Client :: loop](https://www.php.net/manual/en/yar-concurrent-client.loop.php)(\[[callable](https://www.php.net/manual/en/language.types.callable.php)`$callback`\[,[callable](https://www.php.net/manual/en/language.types.callable.php)`$error_callback`\]\] ) :bool—發送所有注冊的并行調用 * [Yar\_Concurrent\_Client :: reset](https://www.php.net/manual/en/yar-concurrent-client.reset.php)(void) :bool—清除所有已注冊的調用 <br> * [Yar\_Server\_Exception](https://www.php.net/manual/en/class.yar-server-exception.php)— Yar\_Server\_Exception類 * [Yar\_Server\_Exception :: getType](https://www.php.net/manual/en/yar-server-exception.gettype.php)—獲取異常的原始類型 <br/> * [Yar\_Client\_Exception](https://www.php.net/manual/en/class.yar-client-exception.php)— Yar\_Client\_Exception類 * [Yar\_Client\_Exception :: getType](https://www.php.net/manual/en/yar-client-exception.gettype.php)—獲取異常的原始類型 傳統的Web應用, 一個進程, 一個請求, 天經地義. 然而, 當一個請求的處理中, 涉及到多出數據源, 并且他們之間具有一定的不依賴性. 還是傳統的Web應用, 一個應用隨著業務快速增長, 開發人員的流轉, 就會慢慢的進入一個惡性循環, 代碼量上只有加法沒有了減法. 因為隨著系統變復雜, 牽一發就會動全局, 而新來的維護者, 對原有的體系并沒有那么多時間給他讓他全面掌握. 即使有這么多時間, 要想掌握以前那么多的維護者的思維的結合, 也不是一件容易的事情... 那么, 長次以往, 這個系統將會越來越不可維護.... 到一個大型應用進入這個惡性循環, 那么等待他的只有重構了. 那么, 能不能對這個系統做解耦呢? 我們已經做了很多解耦了, 數據, 中間件, 業務, 邏輯, 等等, 各種分層. 但到Web應用這塊, 還能怎么分呢, MVC我們已經做過了.... 基于此, Yar或許能解決你遇到的這倆個問題... Yar是一個非常輕量級的RPC框架, 我在實現Yar的時候, 追求了極致的輕量級, 它使用非常簡單, 對于Server端: ~~~ <?php class API { /** * the doc info will be generated automatically into service info page. * @params * @return */ public function api($parameter, $option = "foo") { } protected function client_can_not_see() { } } $service = new Yar_Server(new API()); $service->handle(); ?> ~~~ 和Soap使用方法很相像吧? 是的, 就這樣, 你的API類就可以對外提供服務了.. Yar為了方便開發, 把文檔和接口綁定到了一起, 對于上面的例子, 如果我們是簡單的GET請求這個接口地址的話, 我們就會看到如下的信息頁面: ![](https://img.kancloud.cn/a1/1a/a11a27c18fb822c5a8ee438ee416ceea_673x221.png) 這樣, 我們可以在注釋中,把接口的信息標注好, 就可以讓文檔和接口在一起了. 而對于Client端來說, 簡單的串行調用, 會非常之簡單: ``` <?php $client = new Yar_Client("http://host/api/"); $result = $client->api("parameter); ?> ``` 這樣一來, 如果你有多個服務, 你只需要一個client. 那么, 最激動人心的并行化調用呢? ``` <?php function callback($retval, $callinfo) { var_dump($retval); } Yar_Concurrent_Client::call("http://host/api/", "api", array("parameters"), "callback"); Yar_Concurrent_Client::call("http://host/api/", "api", array("parameters"), "callback"); Yar_Concurrent_Client::call("http://host/api/", "api", array("parameters"), "callback"); Yar_Concurrent_Client::call("http://host/api/", "api", array("parameters"), "callback"); Yar_Concurrent_Client::loop(); //send ?> ``` 這樣, 所有的請求會一次發出, 只要有任何一個請求完成, 回調函數"callback"就會被立即調用. 這里還有一個細節, Yar見縫插針的不會浪費任何時間, 在這些請求發送完成以后, Yar會調用一次callback, 和普通的請求返回回調不同, 這次的調用的$callinfo參數為空. 這樣一來, 我們就可以先發送請求, 然后再第一次回調, 繼續做我們當前進程的工作, 等所有工作結束以后, 再交給Yar去獲取并行RPC的響應 ``` <?php function callback($retval, $callinfo) { if ($callinfo == NULL) { //做本地的邏輯 return TRUE; } //RPC請求返回, 返回值在$retval } ``` 有了這些, 我們就可以把一個Web應用中, 多個數據源并行處理, 從而也能把這些邏輯解耦, 分開部署... ### **鏈接持久化** 也就是YAR\_OPT\_PERSISTENT, 這個配置之前一直有,只不過之前是設計為跨請求的持久化,這次做了優化,變成了基于PHP請求生命期的鏈接保持。 也就是說,當你對一個Yar\_Client設置了YAR\_OPT\_PERSISTEN為true的話,在一次RPC調用結束后,Yar不會銷毀這個鏈接,從而加速后續的針對同樣這個Client的RPC調用,我們來看個例子: ``` <?php function bench($client) { $start = microtime(true); $client->header("connection"); echo microtime(true) - $start, "s\n"; } $client = new Yar_Client("http://remote_host/index.php"); $client->setOpt(YAR_OPT_PERSISTENT, 1); bench($client); bench($client); bench($client); ``` 輸出: ``` 0.090613842010498s 0.045492887496948s 0.045512914657593s ``` 可見,第二次調用的時候,耗時降低了一半,這是因為節省了TCP鏈接建立的耗時。 最后,鏈接會在PHP請求結束以后,整體釋放,也就是PHP請求生命期的存活,不會垮請求,也不用擔心內存泄漏。 不過很遺憾,這個并不能用于加速并行調用: ``` function callback($retval, $callinfo) { global $start; if ($callinfo) { echo "Num ", $callinfo["sequence"] , " costs: ", microtime(true) - $start, "s\n"; } } Yar_Concurrent_Client::call("http://remote_host/index.php", "header", array("connection"), NULL, NULL, array(YAR_OPT_PERSISTENT=>1)); $start = microtime(true); Yar_Concurrent_Client::loop("callback", function($error) { var_dump($error); }); $start = microtime(true); Yar_Concurrent_Client::loop("callback", function($error) { var_dump($error); }); ``` 我們會發現倆次調用沒有加速的效果: ``` Num 1 costs: 0.091023921966553s Num 1 costs: 0.090677976608276s ``` 這跟Yar底層使用的libcurl有關系,從libcurl的官方文檔關于curl_multi_add_handle: >[info]When an easy interface is added to a multi handle, it will use a shared connection cache owned by the multi handle. Removing and adding new easy handles will not affect the pool of connections or the ability to do connection re-use. 也就是說,只要我把一個我們打開的libcurl cp通過curl_multi_add_handle加入到并行隊列,這個cp就會使用libcurl multi自己管理的共享連接池,不會受Yar自己管理的persistent與否影響了。而這個共享是指在整個一次libcurl multi的請求過程中的共享,但事實上因為我們一次會發出所有請求,不會存在一個請求完成下一個請求開始的情況,那么也就不會存在復用了。 不過,我后來觀察到在某些版本之上的libcurl,比如我測試的7.58.0下,可以看到加速的效果(這個是本機測試,所以看起來速度快很多): ``` Num 1 costs: 0.0017080307006836s Num 1 costs: 0.0010600090026855s ``` 后續有時間需要慢慢研究下,從libcurl哪個版本開始的變化。 自定義DNS 這個是來自HuangeChaodian網友的PR,基本上是有的時候,我們需要自定義某個Host的DNS解析結果,比如在測試的時候,把一個Hostname指向本地。 誠然,我們可以使用編輯hosts來達到這個效果, 但如果能在代碼中切換,還是會方便不少,看例子: ``` <?php $client = new Yar_Client("http://remote_host/index.php"); $client->setOpt(YAR_OPT_RESOLVE, "remote_host:80:127.0.0.1"); ``` 這樣,Yar就會把remote_host解析為127.0.0.1了, 可以方便我們做一些本地調試。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看