HTTPクライアントであるGuzzleで並列リクエスを試す


■ 目次

  1. 概要
  2. Guzzleを試してみる
  3. 非同期処理を試してみる

■ 概要

GuzzleとはHTTPリクエストを簡単に送信できるPHPのHTTPクライアントである

HTTPクライアントの中でも現在最も主流となっていて、複数のリクエストを並列で送信することもできる

Guzzleをとりあえず使うところから、並列リクエストの方法も書いてみる

Guzzleのドキュメント(英語)

■ Guzzleを試してみる

準備

検証環境について

$ cat /etc/redhat-release
CentOS release 6.8 (Final)

composer install

$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

guzzle install

$ mkdir sample && cd sample
$ composer require guzzlehttp/guzzle

GETのサンプル

サンプルソース

$ cat sample.php
<?php
require __DIR__ . '/vendor/autoload.php';

$client = new GuzzleHttp\Client();

// Guzzleを使ってAPIを叩く、叩き方は2種類あるので使いやすい方を使う
$response = $client->get('http://httpbin.org/get');
$response = $client->request('GET', 'http://httpbin.org/get');

// ステータスコード取得
var_dump($response->getStatusCode());

// レスポンスボディ取得
// 扱いやすいようにJSONからPHPの配列に変換する
var_dump(json_decode($response->getBody(), true));

サンプル実行

$ php sample.php
int(200)
array(4) {
 ["args"]=>
 array(0) {
 }
 ["headers"]=>
 array(2) {
 ["Host"]=>
 string(11) "httpbin.org"
 ["User-Agent"]=>
 string(39) "GuzzleHttp/6.2.1 curl/7.19.7 PHP/5.6.30"
 }
 ["origin"]=>
 string(13) "126.112.54.50"
 ["url"]=>
 string(22) "http://httpbin.org/get"
}

POSTのサンプル

サンプルソース
オプションについて: request-options

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

$client = new GuzzleHttp\Client();

// 第1引数: HTTPメソッド
// 第2引数: URL
// 第3引数: オプション
$response = $client->request(
  'POST',
  'http://httpbin.org/post',
  [
    // headers: HTTPヘッダを指定できる
    'headers' => [
      'Content-Type' => 'application/json'
    ],
    // form_params: PHPの配列をフォーム形式に変換してリクエストする
    'form_params' => [
      'q' => 'hoge'
    ]
  ]
);
var_dump($response->getStatusCode());
var_dump(json_decode($response->getBody(), true));

■ 非同期処理を試してみる

Promiseとは非同期処理を抽象化したオブジェクト
今回は使わないが複数のPromiseをメソッドチェインで繋げることもできる

Promiseを使ったサンプル

<?php
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
use GuzzleHttp\Psr7\Response;
require __DIR__ . '/vendor/autoload.php';

$urls = [
  'sample1' => 'http://httpbin.org/get',
  'sample2' => 'http://httpbin.org/get',
  'sample3' => 'http://httpbin.org/get',
  'sample4' => 'http://httpbin.org/get',
  'sample5' => 'http://sample.error.url/',
];

$client = new Client();
$promises = [];
$results  = [];

// それぞれのURLに対して非同期でURLを投げる
foreach ($urls as $key => $url) {
  $promises[$key] = $client->requestAsync('GET', $url);
}

// requestが完了するのを待った後、結果によって処理を行う
foreach (Promise\settle($promises)->wait() as $key => $obj) {
  switch ($obj['state']) {
    case 'fulfilled':
      // 成功時
      $results[$key] = $obj['value'];
      break;
    case 'rejected':
      // 失敗時
      $results[$key] = new Response($obj['reason']->getCode());
      break;
    default:
      // 想定外としてエラー扱いにする
      $results[$key] = new Response(0);
  }
}

// 成功したrequestの結果だけ表示する
foreach ($results as $result) {
  if ($result->getReasonPhrase() === 'OK') {
    var_dump(json_decode($result->getBody()->getContents(), true));
  }
}

並列でHTTPリクエストを実行しているのでURLの数を増やしても時間はほとんど変わらない


Be First to Comment

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です