关于协程的优点以及swoole 协程的用法

在上篇文章中php yield关键字以及协程的实现  我们讲到了协程的原理以及运行步骤.

现在我们来继续看下协程的执行顺序.

仙士可博客

协程的运行是交叉式运行(串行),只要你发起了一次协程切换,则会立马暂停当前协程,去运行下一个协程,直到下次代码调度回协程.


协程的优点

看到上面的执行顺序,你可能还是不能理解协程的优点,这个其实是一个很简单的概念,举个例子:

小明烧开水需要10分钟,刷牙需要3分钟,吃早餐需要5分钟,请问做完这些事情总共需要多少分钟?

答案是10分钟,因为在烧开水这个步骤时,不需要坐在那里看水壶烧(异步,io耗时)可以先去刷牙,然后去吃早餐

协程的优点主要在于这里,当遇上io耗时的情况时,这部分的等待时间我们其实可以节约出来,去先处理其他代码逻辑的,直到io完成再继续执行之前的代码.

没错,协程的优点就在于这个.


swoole协程

在swoole中,已经自带了协程管理器,以及异步io的扩展(redis.mysql,http客户端等),我们只要安装好swoole扩展,就可以直接使用协程了,例如以下代码:

$start_time = time();
/*for ($i = 0; $i <= 500; $i++) {
    go(function ()use($i,$start_time){
        $cli = new Swoole\Coroutine\Http\Client('www.baidu.com', 443,true);
        $cli->setHeaders([
            'Host' => "www.baidu.com",
            "User-Agent" => 'Chrome/49.0.2587.3',
            'Accept' => 'text/html,application/xhtml+xml,application/xml',
            'Accept-Encoding' => 'gzip',
        ]);
        $cli->set([ 'timeout' => 0.11]);
        $cli->get('/');
        $cli->close();
        echo  "协程{$i}已完成,耗时".(time()-$start_time).PHP_EOL;
    });
}*/
$start_time = time();
for ($i = 0; $i <= 500; $i++) {
    $url     = 'https://www.baidu.com/';
    $content = file_get_contents($url);
    echo "普通{$i}已完成\n";
}
echo "非携程完成时间:" . (time() - $start_time);

在非协程环境,它的执行顺序和执行时间如下:

仙士可博客


而在注释掉非协程代码,协程环境运行下,它的执行顺序和时间如下:

仙士可博客


为什么会这样呢?我说下具体的流程:

非协程流程

1:先执行$i=0

2:通过file_get_contents获取网页内容

3:获取成功后在进行输出: 普通0已完成

4:继续执行$i=1

...

协程流程

1:先执行$i=0

2:通过异步client类,去请求https://www.baidu.com

3:协程切换不等待获取网页内容,直接跳到$i=1

4:通过异步client类,去请求https://www.baidu.com

....

n:$i=0的请求内容已经完成,切换回$i=0后面的代码,输出"协程0已完成,耗时0"

n+1:通过异步client类,去请求https://www.baidu.com,协程切换不等待获取网页内容,直接跳到$i=n+2

n+2:$i=n的请求内容已经完成,切换回$i=n后面的代码,输出"协程n已完成,耗时5"

....


由这2个流程可以看出一个不同之处:非协程需要等待请求网页的时间,而协程直接跳过了等待的时间,继续往下执行,

也就是上面说的"小明烧开水的时间先去刷牙"

然后,由于协程没有了io耗时,执行速度大大提高,假设请求一次网站需要0.05秒,那500次循环就相当于节省了25秒,这就是为什么协程适合在高并发io场景的原因了





仙士可博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论
  • 本站由白俊遥博客程序搭建
    © 2017-1-17 php20.cn 版权所有 ICP证:闽ICP备17001387号
  • 联系邮箱:1067197739@qq.com