亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

關(guān)于Curl在Swoole協(xié)程中的解決方案詳析

 更新時(shí)間:2019年09月12日 10:31:16   作者:宇潤(rùn)  
這篇文章主要給大家介紹了關(guān)于Curl在Swoole協(xié)程中的解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Swoole具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

眾所周知,在 Swoole 應(yīng)用中,是不推薦使用 Curl 的,因?yàn)?Curl 會(huì)阻塞進(jìn)程。

本文會(huì)用實(shí)際的代碼和數(shù)據(jù),用最直觀的方式,讓你明白為什么。

最后還會(huì)給出 Curl 在 Swoole 中的解決方案,如果不想看分析可以直接拉到最后。

例程對(duì)比

宇潤(rùn)看文章不喜歡那些虛的,所以自己寫也比較實(shí)在,直接來(lái)跑一下代碼,用數(shù)據(jù)看為什么不推薦在 Swoole 使用 Curl。

為了偷懶,我直接用了 YurunHttp 的 Curl 和 Swoole Handler,來(lái)替代那些又臭又長(zhǎng)的 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); // 假設(shè)各種處理耗時(shí)1秒
  $response->end($request->get['id'] . ': ' . date('Y-m-d H:i:s'));
});
$http->start();

test.php

<?php

use Yurun\Util\YurunHttp;
use Yurun\Util\HttpRequest;

require __DIR__ . '/vendor/autoload.php';

define('REQUEST_COUNT', 3);

go(function(){
  // 協(xié)程客戶端
  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); // 請(qǐng)求地址
      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); // 請(qǐng)求地址
      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;
});

運(yùn)行

首次運(yùn)行需要執(zhí)行 composer update 安裝依賴

運(yùn)行 php server.php,啟動(dòng)服務(wù)端

運(yùn)行 php test.php,啟動(dòng)客戶端

運(yùn)行結(jié)果

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"
curl time: 3.0139901638031s

結(jié)果分析

上面的代碼在服務(wù)端延遲 1 秒后返回結(jié)果,模擬實(shí)際業(yè)務(wù)的耗時(shí)。

通過(guò)客戶端的耗時(shí)可以看出,Curl 3 次請(qǐng)求總共耗時(shí) 3 秒多,而協(xié)程客戶端僅耗時(shí) 1 秒多。

因?yàn)榍耙淮握?qǐng)求中,Curl 等待返回內(nèi)容的時(shí)間是干不了其他事情的。而協(xié)程客戶端等待返回內(nèi)容期間,是掛起當(dāng)前協(xié)程,轉(zhuǎn)而再去執(zhí)行其它協(xié)程中的代碼。

解決方案

CoroutineHttpClient

使用 Swoole 內(nèi)置的協(xié)程客戶端實(shí)現(xiàn),適合有一定基礎(chǔ)的開(kāi)發(fā)者使用。

文檔:https://wiki.swoole.com/wiki/...

Guzzle-Swoole

我們?cè)陧?xiàng)目中,可能很少直接寫 curl,但是用到的很多第三方類庫(kù)(如某某云們的 SDK)會(huì)有用到。

這些第三方類庫(kù)通常使用的是 Guzzle 作為 Http 客戶端,而 Guzzle 底層也是使用 Curl 實(shí)現(xiàn)。

宇潤(rùn)專為此種場(chǎng)景研發(fā)了 Guzzle-Swoole 包,引入后可以讓這些 SDK 輕松支持協(xié)程,而不用修改一行代碼。

使用方法

執(zhí)行命令直接安裝依賴:composer require yurunsoft/guzzle-swoole ~1.1

全局設(shè)定處理器:

<?php
require dirname(__DIR__) . '/vendor/autoload.php';

use GuzzleHttp\Client;
use Yurun\Util\Swoole\Guzzle\SwooleHandler;
use GuzzleHttp\DefaultHandler;

DefaultHandler::setDefaultHandler(SwooleHandler::class);

go(function(){
  $client = new Client();
  $response = $client->request('GET', 'http://www.baidu.com', [
    'verify'  => false,
  ]);
  var_dump($response->getStatusCode());
});

手動(dòng)指定 Swoole 處理器:

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Yurun\Util\Swoole\Guzzle\SwooleHandler;

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 是開(kāi)源的PHP HTTP類庫(kù),支持鏈?zhǔn)讲僮?,?jiǎn)單易用。

支持所有常見(jiàn)的GET、POST、PUT、DELETE、UPDATE等請(qǐng)求方式,支持瀏覽器級(jí)別 Cookies 管理、上傳下載、設(shè)置和讀取header、Cookie、請(qǐng)求參數(shù)、失敗重試、限速、代理、證書(shū)等。

3.0 版完美支持Curl、Swoole 協(xié)程;3.2 版支持 Swoole WebSocket 客戶端。

使用方法

執(zhí)行命令直接安裝依賴:composer require yurunsoft/yurun-http ~3.2

<?php
use Yurun\Util\YurunHttp;
use Yurun\Util\HttpRequest;

// 設(shè)置默認(rèn)請(qǐng)求處理器為 Swoole
YurunHttp::setDefaultHandler(\Yurun\Util\YurunHttp\Handler\Swoole::class);

// Swoole 處理器必須在協(xié)程中調(diào)用
go('test');

function test()
{
  $http = new HttpRequest;
  $response = $http->get('http://www.baidu.com');
  echo 'html:', PHP_EOL, $response->body();
}

截止發(fā)稿時(shí),Swoole 4.4 新增的 hook Curl 依然是實(shí)驗(yàn)性功能。雖然宇潤(rùn)曾為該功能貢獻(xiàn)過(guò)一部分代碼,但是由于需要兼容的工作量非常大,有太多 OPTION 不被支持,我個(gè)人是暫時(shí)不推薦使用 hook Curl 的。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

最新評(píng)論