PHP-Swoole协程的使用介绍

1.前言

swoole从4.X版本后开始完整的支持协程的编程,swoole中的协程实质是单线程同步模式,创建新协程后,当协程挂起或者执行结束会让出CPU控制权给父协程继续执行之后的代码。通过Co::sleep可以自动的让出会恢复协程,而Co::yield则是手动的让出协程,并且只能通过Co::resume恢复指定的协程。

2.协程的创建

协程的创建方式有3种:

1.Swoole\Coroutine::create(callable $function, …$args) //原生的创建API

2.go(callable $function, …$args)//短名API

3.原生的协程组件:

Swoole\Coroutine\Client

Swoole\Coroutine\HTTP\Client

Swoole\Coroutine\HTTP2\Client

Swoole\Coroutine\Redis

Swoole\Coroutine\MySQL

Swoole\Coroutine\PostgreSQL

Coroutine\Server

3.协程的执行顺序

<?php
$a = 1;
echo 'step3-cid:' . go(function() {
    global $a;
    echo 'step1:' . $a . PHP_EOL;
    echo 'step2-cid:' . go(function () {
        global $a;
        ++$a;
        co::sleep(3.0);
        echo 'step6-cid:' . go(function () {
            global $a;
            ++$a;
            co::sleep(2.0);
            echo 'step8:' . PHP_EOL;
        }) . PHP_EOL;
        echo "step7:" . PHP_EOL;
    }) . PHP_EOL;
    co::sleep(1.0);
    echo 'step5:' . $a . PHP_EOL;
}) . PHP_EOL;

echo 'step4:' . PHP_EOL;

4.协程通道的使用

通道(Channel)特性和进程间通信的管道类似,而其数据结构则和数组相似。当管道满的时候,push协程会让出CPU给pop协程,当管道为空时,则pop协程会让出CPU给push协程。

<?php
use Swoole\Coroutine as co;
$chan = new co\Channel(1);

co::create(function () use ($chan) {
    for($i = 0; $i < 2; $i++) {
        co::sleep(1.0);
        echo 'start' . PHP_EOL;
        $chan->push($i);
        echo "$i\n";
    }
});

co::create(function () use ($chan) {
    while(1) {
        echo 'handling' . PHP_EOL;
        $data = $chan->pop();
        var_dump($data);
    }
});

go(function() use ($chan) {
   $chan->push(['123']);
    echo 'push' . PHP_EOL;
   $chan->push(['321']);

});

5.协程客户端 setDefer 并发请求收包

协程客户端还支持并发请求,也就是发送异步请求。收包的时间为max(request_time_out),最长的请求时间。

 $n = 5;
    for ($i = 0; $i < $n; $i++) {
        $cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
        $cli->setHeaders([
            'Host' => "local.ad.oa.com",
            "User-Agent" => 'Chrome/49.0.2587.3',
            'Accept' => 'text/html,application/xhtml+xml,application/xml',
            'Accept-Encoding' => 'gzip',
        ]);
        $cli->set([ 'timeout' => 2]);
        $cli->setDefer();
        $cli->get('/test.php');
        $clients[] = $cli;
    }

    for ($i = 0; $i < $n; $i++) {
        $r = $clients [$i]->recv();
        $result[] = $clients[$i]->body;
    }
如无特殊说明,文章均为本站原创,转载请注明出处。如发现有什么不对的地方,希望得到您的指点。

发表评论

电子邮件地址不会被公开。 必填项已用*标注