当前位置 主页 > 网站技术 > 代码类 >

    关于Curl在Swoole协程中的解决方案详析

    栏目:代码类 时间:2019-09-12 12:13

    前言

    众所周知,在 Swoole 应用中,是不推荐使用 Curl 的,因为 Curl 会阻塞进程。

    本文会用实际的代码和数据,用最直观的方式,让你明白为什么。

    最后还会给出 Curl 在 Swoole 中的解决方案,如果不想看分析可以直接拉到最后。

    例程对比

    宇润看文章不喜欢那些虚的,所以自己写也比较实在,直接来跑一下代码,用数据看为什么不推荐在 Swoole 使用 Curl。

    为了偷懒,我直接用了 YurunHttp 的 Curl 和 Swoole Handler,来替代那些又臭又长的 Curl 代码。

    代码
    composer.json

    {  "require": {    "yurunsoft/yurun-http": "~3.0"  }}

    server.php

    <?php$http = new Swoole\Http\Server('127.0.0.1', 9501);$http->on('workerstart', function(){  \Swoole\Runtime::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

    <?phpuse Yurun\Util\YurunHttp;use Yurun\Util\HttpRequest;require __DIR__ . '/vendor/autoload.php';define('REQUEST_COUNT', 3);go(function(){  // 协程客户端  echo 'coroutine http client:', PHP_EOL, PHP_EOL;  $time = microtime(true);  YurunHttp::setDefaultHandler(\Yurun\Util\YurunHttp\Handler\Swoole::class); // 切换为 Swoole Handler  $channel = new \Swoole\Coroutine\Channel;  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 'coroutine http client time: ', (microtime(true) - $time) . 's', PHP_EOL, PHP_EOL;  // curl  echo 'curl:', PHP_EOL, PHP_EOL;  $time = microtime(true);  YurunHttp::setDefaultHandler(\Yurun\Util\YurunHttp\Handler\Curl::class); // 切换为 Curl Handler  $channel = new \Swoole\Coroutine\Channel;  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,启动客户端

    运行结果

    coroutine http client:

    string(22) "1: 2019-09-11 08:35:54"
    string(22) "0: 2019-09-11 08:35:54"
    string(22) "2: 2019-09-11 08:35:54"
    coroutine http client time: 1.0845630168915s

    curl:

    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"