久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx

PHP中yield的使用方法

這篇文章運用簡單易懂的例子給大家介紹PHP中yield的使用方法,代碼非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

成都創新互聯公司-專業網站定制、快速模板網站建設、高性價比豐城網站開發、企業建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式豐城網站制作公司更省心,省錢,快速模板網站建設找我們,業務覆蓋豐城地區。費用合理售后完善,十多年實體公司更值得信賴。

開篇

剛開始接觸PHPyield 的時候,感覺,yield 是什么黑科技,百度一下:yield——協程,生成器。很多文章都在講 IteratorGenerater, 蛤~,這東西是 PHP 迭代器的一個補充。再翻幾頁,就是Go 協程。我出于好奇點開看了下Go 協程, 里面都是 并發線程管道通訊這類字眼,wc,nb, 這tm才是黑科技啊,再回來看PHP,分分鐘想轉 Go

yield 語法加入 PHP

yield語法是在版本5.5加入PHP的,配合迭代器使用,功能上就是 流程控制 代碼,和gotoreturn 類似。

以下就是官方提供的 yield 小例子,通過執行結果,我們可分析當代碼執行到 yield $i 時,他會進行 return $i, 待 echo "$value\n" 后, goto  for ($i = 1; $i <= 3; $i++) {, 對!PHP 的 yield 就是一個能出能進的語法。在z代碼中七進七出,把 $i 平平安安得送了出來。

<?phpfunction gen_one_to_three() {
    for ($i = 1; $i <= 7; $i++) {
        //注意變量$i的值在不同的yield之間是保持傳遞的。
        yield $i;
    }}$generator = gen_one_to_three();foreach ($generator as $value) {
    echo "$value\n";}// output12...67

我們遇到了什么問題

寫代碼就是解決問題。我們來看看他們遇到了什么問題:php官方呢,需要言簡意賅地把yield介紹給大家。一部分網友呢,需要在有限的資源內完成大文件操作。而我們的鳥哥。面對的一群對當下yield的教程停留于初級而不滿意的phper,就以一個任務調度器作為例子,給大家講了一種yield高級用法。

php.net:生成器語法,
PHP如何讀取大文件,
風雪之隅:在PHP中使用協程實現多任務調度.

提出問題,再用yield來解答,看到以上答案,我覺得呢,這PHP協程不過如此(Go協程相比 )。

有句話——一個好問題比答案更重要,目前廣大網友還沒有給yield提出更好,更困難的問題。

yield這個進進出出的語法,很多舉例都是再讓yield做迭代器啊,或者利用低內存讀取超大文本的Excelcsv什么的,再高級就是用它實現一個簡單的任務調度器,并且這個調度器,一看代碼都差不多。

我來出道題

正如一個好的問題,比答案更有價值

  1. 用PHP實現一個 Socket Server,他能接收請求,并返回Server的時間。

好,這是第一個問題,鋪墊。 官方答案

  1. 在原來的代碼上,我們加個需求,該Socket Server 處理請求時,依賴其他 Socket Server,還需要有 Client 功能。也就是他能接收請求,向其它Server發起請求。

這是第二個問題,也是鋪墊。

  1. 原來的Socket Server同一時間只能服務一個客戶,希望能實現一個 非阻塞I/O Socket Server, 這個 Server 內有 Socket Client 功能,支持并發處理收到的請求,和主動發起的請求。要求不用多線程,多進程。

這個問題,還是鋪墊,這幾個問題很干,大家可以想一想,2,3題的答案,都放在一個腳本里了:nio_server.php

以上這段代碼,我列舉了一個具體的業務,就是用戶請求購物車加購動作, 而購物車服務呢,又需要和 產品服務,庫存服務,優惠服務 交互,來驗證加購動作可行性。有同步,異步方式請求,并做對比。

后續還有很多代碼,我都放gitee鏈接了。使用方法,見readme.md

  1. 最后一個問題:在PHP中,用同步寫代碼,程序呢異步執行?需要怎么調整代碼。

提示:這個和 PHPyield 語法有關。

再提示:yield 語法特征是什么,進進出出!

看著我們的代碼,同步, 異步,進進出出你想到了什么?

看到代碼,同步處理模式下,這三個函數checkInventory checkProduct checkPromo 時,發起請求,并依次等待返回的結果,這三個函數執行后,再響應客戶請求。

異步處理模式下,這三個函數發起請求完畢后,代碼就跳出循環了,然后是在select()下的一個代碼分支中接收請求, 并收集結果。每次收到結果后判斷是否完成,完成則響應客戶端。

那么能不能這樣:在異步處理的流程中,當 Server收到 自己發起的 client 有數據響應后,代碼跳到 nio_server.php 的 247行呢,這樣我們的收到請求校驗相關的代碼就能放到這里,編碼能就是同步,容易理解。不然,client 的響應處理放在 280 行以后,不通過抓包,真的很難理解,執行了第 247 行代碼后,緊接著是從 280 行開始的。

誒~這里是不是有 進進出出那種感覺了~ 代碼從 247 行出去,開始監聽發出 Client 響應,收到返回數據,帶著數據再回到 247 行,繼續進行邏輯校驗,綜合結果后,再響應給客戶端。

用yield來解決問題

基于 yield 實現的,同步編碼,"異步"I/OSocket Server 就實現了。代碼。

這里 “異步” 打了引號,大佬別扣這個字眼了。 該是非阻塞I/O

不等大家的答案了,先上我的結果代碼吧,代碼呢都放在這個目錄下了。

gitee https://gitee.com/xupaul/PHP-generator-yield-Demo/tree/master/yield-socket

運行測試代碼

clone 代碼到本地后,需要拉起4個 command 命令程序:

拉起3個第三方服務
## 啟動一個處理耗時2s的庫存服務$ php ./other_server.php 8081 inventory 2## 啟動一個處理耗時4s的產品服務$ php ./other_server.php 8082 product 4## 監聽8083端口,處理一個請求 耗時6s的 promo 服務$ php ./other_server.php 8083 promo 6
啟動購物車服務
## 啟動一個非阻塞購物車服務$ php ./async_cart_server.php 

## 或者啟動一個一般購物車服務$ php ./cart_server.php
發起用戶請求
$ php ./user_client.php

運行結果呢如下,通過執行的時間日志,可得這三個請求是并發發起的,不是阻塞通訊。

在看我們的代碼,三個函數,發起socket請求,沒有設置callback,而是通過yield from 接收了三個socket的返回結果。

也就是達到了,同步編碼,異步執行的效果。

運行結果

非阻塞模式

client 端日志:
PHP中yield的使用方法

通過以上 起始時間結束時間 ,就看到這三個請求耗時總共就6s,也就按照耗時最長的promo服務的耗時來的。也就是說三個第三方請求都是并發進行的。

cart server 端日志:
PHP中yield的使用方法

而 cart 打印的日志,可以看到三個請求一并發起,并一起等待結果返回。達到非阻塞并發請求的效果。

阻塞模式

client 端日志:
PHP中yield的使用方法

以上是阻塞方式請求,可以看到耗時 12s。也就是三個服務加起來的耗時。

cart server 端日志:
PHP中yield的使用方法

cart 服務,依次阻塞方式請求第三方服務,順序執行完畢后,共耗時12s,當然如果第一個,獲第二個服務報錯的話,會提前結束這個檢查。會節約一點時間。

工作原理

這里就是用到了 yield 的工作特點——進進出出,在發起非阻塞socket請求后,不是阻塞方式等待socket響應,而是使用yield跳出當前執行生成器,等待有socket響應后,在調用生成器的send方法回到發起socket請求的函數內,在 yield from Async::all() 接收數據響應數據搜集完畢后,返回。

和Golang比一比

考慮到網速原因,我這就放上一個國內教程鏈接:Go 并發 教程

php的協程是真協程,而Go是披著協程外衣的輕量化線程(“協程”里,都玩上“鎖”了,這就是線程)。

我個人偏愛,協程的,覺得線程的調度有一定隨機性,因此需要鎖機制來保證程序的正確,帶來了額外開銷。協程的調度(換入換出)交給了用戶,保證了一段代碼執行連續性(當然進程級上,還是會有換入換出的,除非是跨進程的資源訪問,或者跨機器的資源訪問,這時,就要用到分布式鎖了,這里不展開討論),同步編碼,異步執行,只需要考慮那個哪個方法會有IO交互會協程跳出即可。

和NodeJS比劃一下

Javascript 和 PHP 兩個腳本語言有很多相似的地方,弱類型,動態對象,單線程,在Web領域生態豐富。不同的是,Javascript在瀏覽器端一開始就是異步的(如果js發起網絡請求只能同步進行,那么你的網頁渲染線程會卡住),例如AjaxsetTimeoutsetInterval,這些都是異步+回調的方式工作。

基于V8引擎而誕生的NodeJS,天生就是異步的,在提供高性能網絡服務有很大的優勢,不過它的IO編碼范式么。。。剛開始是 回調——毀掉地獄,后來有了Promise——屏幕豎起來看,以及Generator——遇事不絕yield一下吧,到現在的Async/Await——語法糖?真香!

可以說JS的委員非常勤快,在異步編程范式的標準制定也做的很好(以前我嘗試寫NodeJS時,幾個回調就直接把我勸退了),2009年誕生的NodeJS有點后來居上的意思。目前PHP只是趕上了協程,期待PHP的Async/Await語法糖的實現吧。

PHP yield 使用注意事項

一旦使用上 yield 后,就必須注意調用函數是,會得到函數結果,還是 生成器對象。PHP 不會自動幫你區別,需要你手動代碼判斷結果類型—— if ($re instanceof \Generator) {}, 如果你得到的是 生成器,但不希望去手動調用 current() 去執行它,那么在生成器前 使用 yield from 交給上游(框架)來解決。

爆改 Workerman

博客寫到這,就開始手癢癢了,看到Workerman框架,我在基礎上二開,使其能——同步編碼,異步執行

代碼已放到:PaulXu-cn/CoWorkerman.git

目前還是dev階段,大家喜歡可以先 體驗一波。

$ composer require paulxu-cn/co-workerman

一個簡單的單線程 TCP Server

<?php// file: ./examples/example2/coWorkermanServer.php , 詳細代碼見github$worker = new CoWorker('tcp://0.0.0.0:8080');// 設置fork一個子進程$worker->count = 1;$worker->onConnect = function (CoTcpConnection  $connection) {
    try {
        $conName = "{$connection->getRemoteIp()}:{$connection->getRemotePort()}";
        echo PHP_EOL . "New Connection, {$conName} \n";

        $re = yield from $connection->readAsync(1024);
        CoWorker::safeEcho('get request msg :' . $re . PHP_EOL );

        yield from CoTimer::sleepAsync(1000 * 2);

        $connection->send(json_encode(array('productId' => 12, 're' =>true)));

        CoWorker::safeEcho('Response to :' . $conName . PHP_EOL . PHP_EOL);
    } catch (ConnectionCloseException $e) {
        CoWorker::safeEcho('Connection closed, ' . $e->getMessage() . PHP_EOL);
    }};CoWorker::runAll();

這里設置fork 一個worker線程,處理邏輯中帶有一個sleep() 2s的操作,依然不影響他同時響應多個請求。

啟動測試程序
## 啟動CoWorker服務$ php ./examples/example2/coWorkermanServer.php start## 啟動請求線程$ php ./examples/example2/userClientFork.php
運行結果

PHP中yield的使用方法

綠色箭頭——新的請求,紅色箭頭——響應請求

從結果上看到,這一個worker線程,在接收新的請求同時,還在回復之前的請求,各個連接交錯運行。而我們的代碼呢,看樣子就是同步的,沒有回調。

CoWorker購物車服務

好的,這里我們做幾個簡單的微服務模擬實際應用,這里模擬 用戶請求端購物車服務庫存服務產品服務。 模擬用戶請求加購動作,購物車去分別請求 庫存,產品 校驗用戶是否可以加購,并響應客戶請求是否成功。

代碼我就不貼了,太長了,麻煩移步 CoWorkerman/example/example5/coCartServer.php

運行命令
## 啟動庫存服務$ php ./examples/example5/otherServerFork.php 8081 inventory 1## 啟動產品服務$ php ./examples/example5/otherServerFork.php  8082 product 2
## 啟動CoWorker 購物車服務$ php ./examples/example5/coCartServer.php start
## 用戶請求端$ php ./examples/example5/userClientFork.php
運行結果

PHP中yield的使用方法

黃色箭頭——新的用戶請求,藍色箭頭——購物車發起庫存,產品檢查請求,紅色箭頭——響應用戶請求

從圖中看到也是用1個線程服務多個連接,交錯運行。

好的,那么PHP CoWorkerman 也能像 NodeJS 那樣用 Async/Await 那樣同步編碼,異步運行了。

快來試試這個 CoWorkerman 吧:

$ composer require paulxu-cn/co-workerman

工作原理

workerman內的worker進程遇到阻塞函數的處理方式時,會等待IO返回,如果這個時候,又有了新的請求,那么閑的worker會競爭到這個新的連接。

我在上圖worker5中,描述了一個AsyncTCPConnection使用情況,woker內發起了一個非阻塞請求,并注冊了回調函數,然后程序繼續運行到結束。當異步請求響應時,就需要通過其他方式去響應(如自己再發起一個請求告知請求方)。

在下圖中CoWorkerman,也是多個Worker競爭新的請求,當worker1收到一個新的請求,會產生一個生成器,生成器內發起異步請求,并注冊響應回調,請求響應后,回到該生成器跳出(yield)的地方,繼續執行代碼。

發起異步請求,并注冊回調函數,這些默認工作CoWorkerman框架內已做了,回調函數內工作是:收到數據,并發給 發起該請求的生成器。

這例子中,通過調用 Promise:all() 發起多個請求,并監聽結果返回,待所有的響應返回再繼續運行生成器

在程序yield跳出后,該worker就處于事件循環狀態($event->loop()),也就是多路監聽:請求端口,第三方客戶端請求響應端口。這個時候如果:

  1. 有新的請求來,他和其他 worker 競爭新的請求,如果競爭到了,則該worker內又產生一個新的 生成器。
  2. 客戶端有響應,則調用回調函數
  3. 客戶端都響應了,繼續運行 生成器程序。

從1中,我們可假設,如果就一個 Worker,那么該 Worker 可以在上一個請求未完成情況下,繼續接受處理下一個請求。也就是 CoWorkerman 可以在單 Worker 下運行,并發處理多個請求。

當然,這里也有個前提,單 Worker 模式內不能運行阻塞函數,一旦阻塞,后續請求就會堵在網卡。所以,除非對自己的代碼非常了解,如果用到第三方庫,那么我還是建議你在多 Worker 模式下運行 CoWorkerman,阻塞時,還有其他Worker兜住新請求。

CoWorkerman 的意義

  1. 用同步的代碼,發起異步請求,多個請求可并發,從IO串行等待,改為并行等待,減少無畏的等待時間。提高業務程序的效率同時,不降低代碼可讀性。
  2. 在一個線程內通過事件循環,盡可能處理多個請求,緩解了一個請求一個線程帶來的頻繁線程切換,從核心上提高運行效率。

CoWorkerman 生態位

適合處理純Socket請求的應用,如Workerman Gateway,或者是 大前端 整合多個服務RPC結果, 綜合后返給前三頁這樣的場景.

日志記錄是每個程序最基本需求,由于寫文件函數是阻塞的,建議用消息隊列,或者redis隊列,更或者跳過Logstash直接丟Elasticsearch.

CoWorkerman有他的局限性,也有他自己位置。

關于PHP中yield的使用方法就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

新聞標題:PHP中yield的使用方法
URL地址:http://www.js-pz168.com/article8/jcipop.html

成都網站建設公司_創新互聯,為您提供企業網站制作外貿網站建設全網營銷推廣Google網站排名

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

成都網站建設公司
久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx
日韩精品专区在线| 丝袜诱惑亚洲看片| 日本不卡1234视频| 成人黄页毛片网站| 欧美日韩在线观看一区| 欧美日韩视频在线一区二区| 久久九九全国免费| 亚洲成av人片在www色猫咪| 国产成人精品www牛牛影视| 国产在线播放一区二区| 91久久精品一区二区三区| 久久先锋影音av| 午夜激情综合网| 99麻豆久久久国产精品免费| 欧美午夜精品久久久久免费视| 欧美日韩aaaaa| 亚洲欧洲国产日韩| 国产一区二区三区高清播放| 国产一区二区视频在线免费观看| 91福利精品视频| 久久久久久久久久看片| 日韩电影免费在线看| 5g影院天天爽成人免费下载| 色综合色综合色综合色综合色综合| 精品日韩99亚洲| 性做久久久久久久免费看| 99国产精品国产精品久久| 亚洲国产精品日韩| 欧美精品一区二区不卡| 舔着乳尖日韩一区| 成人av男人的天堂| 欧美体内she精高潮| 亚洲欧洲一区二区三区| 国产精品一区三区| 日韩欧美一区二区三区四区五区| 欧美大胆人体bbbb| 日韩专区在线视频| 国产乱码精品一区二区三区卡| 欧美日韩午夜在线视频| 伊人婷婷欧美激情| 91社区在线播放| 欧美日韩亚洲丝袜制服| 亚洲精品午夜久久久| 成人综合在线网站| 在线日韩av永久免费观看| 国产精品午夜在线观看| 国产福利一区在线| 一本久道久久综合狠狠爱亚洲精品| 国产色91在线| 国产成人三级在线观看| 亚洲一区二区在| 中文字幕不卡一区| 国产不卡在线一区| 在线视频综合导航| 亚洲综合清纯丝袜自拍| 99久久国产免费免费| 4438x亚洲最大成人网| 无码av中文一区二区三区桃花岛| 国产精品xxxx| 日韩美一区二区三区| 久久精品国产99国产| 亚洲丰满在线| 中文字幕一区二区三区精华液| 岛国一区二区三区| 精品视频在线视频| 午夜一区二区三区视频| 久久亚洲午夜电影| 国产日韩欧美精品综合| 处破女av一区二区| 精品视频一区三区九区| 性做久久久久久| 欧洲亚洲一区二区三区四区五区| 国产日本亚洲高清| 成人av综合一区| 欧美日韩黄色一区二区| 日韩国产精品久久久久久亚洲| 欧美精品国产精品久久久| 国产欧美一区二区精品性| 成人性视频免费网站| 欧美精品黑人性xxxx| 美国精品在线观看| 色综合天天在线| 亚洲风情在线资源站| 任我爽在线视频精品一| 亚洲欧美综合色| 国产精品制服诱惑| 国产欧美一区二区精品婷婷| 91在线视频免费91| 26uuu另类欧美亚洲曰本| 国产成人av电影在线| 欧美老人xxxx18| 久久国产精品99久久久久久老狼 | 蜜臀a∨国产成人精品| 日韩在线国产| 亚洲黄色尤物视频| 美脚丝袜一区二区三区在线观看| 国产精品久久久久aaaa樱花| 成人动漫在线观看视频 | av在线播放一区二区三区| 日韩一区二区三区三四区视频在线观看| 久久精品免费看| 精品视频1区2区3区| 久久精品99国产精品日本| 在线观看中文字幕不卡| 另类小说图片综合网| 欧美性做爰猛烈叫床潮| 久久国产婷婷国产香蕉| 欧美私人免费视频| 国内外成人在线| 欧美日韩国产免费一区二区| 精品无人区卡一卡二卡三乱码免费卡 | 精品乱色一区二区中文字幕| 国产精品久久久久aaaa樱花 | 一本一生久久a久久精品综合蜜 | 国产精品国模大尺度私拍| 国产女人18水真多18精品一级做| 国产精品99久久久久久久| 国产精品国产三级国产普通话99| 国产中文一区二区| 亚洲毛片av在线| 亚洲成人自拍视频| 免费成人深夜小野草| 欧美日韩成人高清| 成人黄色国产精品网站大全在线免费观看| 欧美sm极限捆绑bd| 成人av网站观看| 亚洲精品国产精华液| 亚洲视频小说| 精品一区二区三区在线视频| 欧美一区二区在线免费观看| 成人sese在线| 国产精品久久久久久久蜜臀| 欧美极品一区二区| 日韩不卡一二三区| 7777精品伊人久久久大香线蕉超级流畅 | 99精品视频一区二区| 欧美激情中文字幕| 欧美日韩精品久久久免费观看| 亚洲国产视频直播| 欧美在线观看视频在线| 国产精品羞羞答答xxdd| 久久久蜜桃精品| 久久久久久高清| 亚洲www啪成人一区二区麻豆 | 麻豆精品蜜桃一区二区三区| 亚洲国产综合91精品麻豆| 91黄色免费网站| 国产69精品久久久久毛片| 日本一区二区三区在线观看| 欧美午夜精品久久久久久蜜| 蜜桃一区二区三区在线| 日韩欧美一区电影| 成人av在线看| 亚洲三级小视频| 色老头久久综合| 夫妻av一区二区| 国产精品萝li| 色综合一区二区| 精品三级在线观看| 韩国成人一区| 日韩电影免费在线| 欧美一区二区三级| 国内精品一区二区| 日韩国产高清影视| 欧美电视剧免费观看| 久草热久草热线频97精品| 日韩激情av在线| 日韩精品专区在线影院重磅| 国内精品久久国产| 日本人妖一区二区| 久久久久久久久蜜桃| 日韩一区二区三区高清| 国产激情视频一区二区在线观看| 国产区在线观看成人精品| 一区二区三区av在线| 成人免费毛片高清视频| 亚洲免费在线观看| 欧美精品一二三四| 国内外成人免费视频| 久久精品久久综合| 日本一区二区久久| 日本精品一区二区三区四区的功能| 99视频精品免费视频| 亚洲成人动漫在线免费观看| 日韩欧美三级在线| 日韩精品欧美专区| 成人app在线观看| 亚洲一级二级三级在线免费观看| 91精品国产综合久久福利软件| 久久国产精品99久久久久久丝袜| 卡一卡二国产精品| 国产精品乱码一区二区三区软件| 91福利小视频| 国产在线一区二区三区欧美| 九九视频精品免费| 亚洲男人都懂的| 在线播放91灌醉迷j高跟美女 | 一区二区三区四区视频精品免费| 7777精品久久久大香线蕉 | www.欧美色图|