关于Curl在Swoole协程中的处理方案详析
发布时间:2022-06-30 14:17:21 所属栏目:PHP教程 来源:互联网
导读:前言 众所周知,在 Swoole 应用中,是不推荐使用 Curl 的,因为 Curl 会阻塞进程。 本文会用实际的代码和数据,用最直观的方式,让你明白为什么。 最后还会给出 Curl 在 Swoole 中的解决方案,如果不想看分析可以直接拉到最后。 例程对比 宇润看文章不喜欢那
前言 众所周知,在 Swoole 应用中,是不推荐使用 Curl 的,因为 Curl 会阻塞进程。 本文会用实际的代码和数据,用最直观的方式,让你明白为什么。 最后还会给出 Curl 在 Swoole 中的解决方案,如果不想看分析可以直接拉到最后。 例程对比 宇润看文章不喜欢那些虚的,所以自己写也比较实在,直接来跑一下代码,用数据看为什么不推荐在 Swoole 使用 Curl。 server.php <?php $http = new SwooleHttpServer('127.0.0.1', 9501); $http->on('workerstart', function(){ SwooleRuntime::enableCoroutine(); }); $http->on('request', function ($request, $response) { sleep(1); // 假设各种处理耗时1秒 $response->end($request->get['id'] . ': ' . date('Y-m-d H:i:s')); }); $http->start(); test.php <?php use YurunUtilYurunHttp; use YurunUtilHttpRequest; require __DIR__ . '/vendor/autoload.php'; define('REQUEST_COUNT', 3); go(function(){ // 协程客户端 echo 'coroutine http client:', PHP_EOL, PHP_EOL; }); } for($i = 0; $i < REQUEST_COUNT; ++$i) { $channel->pop(); } $channel->close(); echo 'coroutine http client time: ', (microtime(true) - $time) . 's', PHP_EOL, PHP_EOL; // curl echo 'curl:', PHP_EOL, PHP_EOL; $time = microtime(true); YurunHttp::setDefaultHandler(YurunUtilYurunHttpHandlerCurl::class); // 切换为 Curl Handler $channel = new SwooleCoroutineChannel; for($i = 0; $i < REQUEST_COUNT; ++$i) { go(function() use($channel, $i){ $http = new HttpRequest; $response = $http->get('http://127.0.0.1:9501/?id=' . $i); // 请求地址 var_dump($response->body()); $channel->push(1); }); } for($i = 0; $i < REQUEST_COUNT; ++$i) { $channel->pop(); } $channel->close(); echo 'curl time: ', (microtime(true) - $time) . 's', PHP_EOL, PHP_EOL; }); 运行 首次运行需要执行 composer update 安装依赖 运行 php server.php,启动服务端 运行 php test.php,启动客户端 运行结果 string(22) "0: 2019-09-11 08:35:55" string(22) "1: 2019-09-11 08:35:56" string(22) "2: 2019-09-11 08:35:57" curl time: 3.0139901638031s 结果分析 上面的代码在服务端延迟 1 秒后返回结果,模拟实际业务的耗时。 通过客户端的耗时可以看出,Curl 3 次请求总共耗时 3 秒多,而协程客户端仅耗时 1 秒多。 因为前一次请求中,Curl 等待返回内容的时间是干不了其他事情的。而协程客户端等待返回内容期间,是挂起当前协程,转而再去执行其它协程中的代码。 解决方案 CoroutineHttpClient 使用 Swoole 内置的协程客户端实现,适合有一定基础的开发者使用。 文档:https://wiki.swoole.com/wiki/... Guzzle-Swoole 我们在项目中,可能很少直接写 curl,但是用到的很多第三方类库(如某某云们的 SDK)会有用到。 这些第三方类库通常使用的是 Guzzle 作为 Http 客户端,而 Guzzle 底层也是使用 Curl 实现。 宇润专为此种场景研发了 Guzzle-Swoole 包,引入后可以让这些 SDK 轻松支持协程,而不用修改一行代码。 使用方法 执行命令直接安装依赖:composer require yurunsoft/guzzle-swoole ~1.1 全局设定处理器: <?php DefaultHandler::setDefaultHandler(SwooleHandler::class); go(function(){ $client = new Client(); $response = $client->request('GET', 'http://www.phpfensi.com', [ 'verify' => false, ]); var_dump($response->getStatusCode()); }); 手动指定 Swoole 处理器: use GuzzleHttpClient; use GuzzleHttpHandlerStack; use YurunUtilSwooleGuzzleSwooleHandler; go(function(){ $handler = new SwooleHandler(); $stack = HandlerStack::create($handler); $client = new Client(['handler' => $stack]); $response = $client->request('GET', 'http://www.baidu.com', [ 'verify' => false, ]); var_dump($response->getBody()->__toString(), $response->getHeaders()); }); YurunHttp YurunHttp 是开源的PHP HTTP类库,支持链式操作,简单易用。 支持所有常见的GET、POST、PUT、DELETE、UPDATE等请求方式,支持浏览器级别 Cookies 管理、上传下载、设置和读取header、Cookie、请求参数、失败重试、限速、代理、证书等。 3.0 版完美支持Curl、Swoole 协程;3.2 版支持 Swoole WebSocket 客户端。 (编辑:开发网_开封站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |