swoole4.0可使用协程+通道的全新编程模式,代替异步回调,应用层可使用完全同步的编程方式,底层自动实现异步I/O
下面会通过一段代码,来帮助大家理解swoole的协程
<?php
use Swoole\Coroutine\Http\Client;
//此方法记录执行时间
function timediff($time)
{
return microtime(true) - $time;
}
//创建http server
$http = new Swoole\Http\Server("0.0.0.0", 9501);
$http->set([
//"daemonize" => true,
"worker_num" => 1,
]);
$http->on('request', function ($request, $response) {
//浏览器会自动发起这个请求,这也是很多人碰到的一个问题:
//为什么我浏览器打开网站,收到了两个请求?
if ($request->server['path_info'] == '/favicon.ico') {
$response->end('');
return;
}
$time = microtime(true);
$response->header("content-type", "text/html; charset=UTF-8");
$response->write("1. 接受请求,此处被执行, 第" . __LINE__ . "行, 时间" . $time . "<br/>");
//启动第一个协程
go(function () use ($response) {
$time = microtime(true);
$response->write("2. 进入第一个协程,发起http请求taobao, 第" . __LINE__ . "行, 时间:" . $time . "<br/>");
//启动一个协程客户端client,请求淘宝首页
$cli = new Client('www.taobao.com', 443, true);
$cli->setHeaders([
'Host' => "www.taobao.com",
"User-Agent" => 'Chrome/49.0.2587.3',
'Accept' => 'text/html,application/xhtml+xml,application/xml',
'Accept-Encoding' => 'gzip',
]);
$cli->set(['timeout' => 1]);
//调用get方法,协程挂起,
$cli->get('/index.php');
//会等待i/o数据返回,才会继续执行下面
$response->write("7. get回taobao数据,唤起协程,此处被执行, 第" . __LINE__ . "行, 执行时间" . timediff($time) . "<br/>");
$cli->close();
});
//上面get挂起协程后,后立马执行这一行
$response->write("3 cli->get时挂起协程了,此处被执行,不会被阻塞, 第" . __LINE__ . "行, 时间:" . microtime(true) . "<br/>");
//启动第二个协程
go(function () use ($response) {
$time = microtime(true);
$response->write("4. 进入第二个协程,发起http请求baidu, 第" . __LINE__ . "行, 时间:" . $time . "<br/>");
//启动一个协程客户端client,请求百度首页
$cli = new 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' => 1]);
//调用get方法,协程挂起,
$cli->get('/index.php');
//会等待i/o数据返回,才会继续执行下面
$response->write("6. get回baidu数据,唤起协程,此处被执行,正常这个先返回,因为ping百度更快,说明两个协程也是并发执行的, 第" . __LINE__ . "行, 执行时间" . timediff($time) . "<br/>");
$cli->close();
});
//第二个协程get时挂起,执行到这一步
$response->write("5 cli->get时挂起协程了,此处被执行,不会被阻塞, 第" . __LINE__ . "行, 时间:" . microtime(true) . "<br/>");
});
$http->start();
运行
1、保存为http.php
2、执行 php http.php
3、浏览器打开:http://127.0.0.1:9501/
几个关键点:
Swoole的协程是单进程的
代码遇到i/o操作会挂起协程
协程之间是并发的,相互不堵塞
预告:下一篇用代码实现类似golang的waitgroup功能
PHP饭米粒(phpfamily) 由一群靠谱的人建立,愿为PHPer带来一些值得细细品味的精神食粮!
饭米粒只发原创或授权发表的文章,不转载网上的文章
所发的文章,均可找到原作者进行沟通。
也希望各位多多打赏(算作稿费给文章作者),更希望大家多多投搞。
投稿请联系:
本文由 半桶水 授权 饭米粒 发布,转载请注明本来源信息和以下的二维码(长按可识别二维码关注)
文章评论