关于协程的优点以及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)