加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

关于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 客户端。

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读