基於swoole的swoolefy實現類似go的waitGroup多併發協程排程
swoolefy是一個基於swoole實現的輕量級高效能的常駐記憶體型的API和Web應用服務框架, 高度封裝了http,websocket,udp伺服器,以及基於tcp實現可擴充套件的rpc服務, 同時支援composer包方式安裝部署專案。基於實用,swoolefy抽象Event事件處理類, 實現與底層的回撥的解耦,支援協程排程,同步|非同步呼叫,全域性事件註冊,心跳檢查,非同步任務,多程序(池)等, 內建view、log、session、mysql、redis、mongodb等常用元件等。
目前swoolefy4.2+版本完全支援swoole4.2.13+的協程,推薦使用swoole4.3+
GitHub:https://github.com/bingcool/s...
下面主要講解一下如何實現了類似go的waitGroup的功能
1、定義GoWaitGroup的類:
<?php /** +---------------------------------------------------------------------- | swoolefy framework bases on swoole extension development, we can use it easily! +---------------------------------------------------------------------- | Licensed ( https://opensource.org/licenses/MIT ) +---------------------------------------------------------------------- | Author: bingcool <[email protected] || [email protected]> +---------------------------------------------------------------------- */ namespace Swoolefy\Core; use Swoole\Coroutine\Channel; class GoWaitGroup { /** * @var int */ private $count = 0; /** * @var Channel */ private $chan; /** * @var array */ private $result = []; /** * WaitGroup constructor */ public function __construct() { $this->chan = new Channel; } /** * add */ public function go(\Closure $go_func = null) { $this->count++; if($go_func instanceof \Closure) { go($go_func); } } /** * start */ public function start() { $this->count++; return $this->count; } /** * done */ public function done(string $key, $data = null) { if(!empty($data)) { $this->result[$key] = $data; } $this->chan->push(1); } /** * wait */ public function wait() { while($this->count--) { $this->chan->pop(); } $result = $this->result; $this->result = []; $this->count = 0; return $result; } }
2、在swoolefy中呼叫
class GroupController extends BController { public function waitgroup() { // 建立一個waitGroup例項 $wg = new \Swoolefy\Core\GoWaitGroup(); // 第一種方式,直接$wg->go()函式中執行go的協程函式 $wg->go(function() use ($wg) { // 掛起協程 $fp = stream_socket_client("tcp://www.baidu.com:80", $errno, $errstr, 30); // 協程返回的資料 $wg->done('mysql', 'mysql'); }); $wg->go(function() use ($wg) { sleep(1); $wg->done('tengxun', 'weixin and qq'); }); //掛起當前協程,等待所有任務完成後恢復 //$result = $wg->wait(); //這裡 $result 包含了 1 個任務執行結果 //var_dump($result); //第二種方式,新增$wg->start(),啟動協程,然後使用swoole的原生go執行協程函式 $wg->start(); go(function () use ($wg) { // 掛起協程 sleep(1); $wg->done('taobao', 'ali baba'); }); //第二種方式,新增$wg->start(),啟動協程,然後使用swoole的原生go執行協程函式 $wg->start(); go(function () use ($wg) { // 掛起協程 sleep(1); $wg->done('baidu', 'baidu'); }); // 以上三個協程將會併發呼叫,wait()函式實現等待三個協程資料返回 //掛起當前協程,讓出cpu控制權,cpu可以做其他的事情,直到待所有任務完成後恢復 $result = $wg->wait(); //這裡 $result 包含了 2 個任務執行結果 var_dump($result); } }
至此一個最簡單的併發呼叫就完成了,你可以愉快使用gowaitGroup的協程呼叫了