LoginSignup
35
34

More than 1 year has passed since last update.

Guzzleでの非同期リクエスト

Last updated at Posted at 2018-03-24

環境

PHP5.6
Guzzle6.3

公式ドキュメント:
http://docs.guzzlephp.org/en/stable/index.html

guzzle インストール

composerでインストールします。

composer require guzzlehttp/guzzle

簡易版非同期リクエスト

require_once(dirname(__FILE__) . '/vendor/autoload.php');
use GuzzleHttp\Client;

$client = new Client();
//$client = new \GuzzleHttp\Client(['cookies' => true]); //クッキーを利用したい場合
//$client = new \GuzzleHttp\Client(['debug' => true]); //通信内容をデバッグしたい場合

$promises[] = $client->requestAsync('GET', 'https://sample.com/1.html');
$promises[] = $client->requestAsync('GET', 'https://sample.com/2.html');
$promises[] = $client->requestAsync('GET', 'https://sample.com/3.html');
$promises[] = $client->requestAsync('GET', 'https://sample.com/4.html');
$promises[] = $client->requestAsync('GET', 'https://sample.com/5.html');

$responses = \GuzzleHttp\Promise\all($promises)->wait();

$result = [];
foreach ($responses as $response) {
    $result[] = [
      'html'             => $response->getBody()->getContents(),
      'status_code'      => $response->getStatusCode(), //ステータスコード
      'reason_phrase'    => $response->getReasonPhrase(), //
      'protocol_version' => $response->getProtocolVersion(),
      'response_header'  => $response->getHeaders()
    ];
}

var_dump($result);
  • 5リクエストを非同期リクエストします
  • 非同期なので、$resultに入ってくるレスポンスは順不同
  • 非同期でPOSTしたい場合の例は下記です。(フォーム送信したいデータがある・ヘッダ指定したいケース)
$config = [
  //ヘッダ指定
  'headers' => [
      'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
      'Accept-Encoding' => 'gzip, deflate, br',
      'Accept-Language' => 'ja,en-US;q=0.9,en;q=0.8',
      'Cache-Control' => 'max-age=0',
      'Connection' => 'keep-alive',
      'Host' => 'sample.com',
      'Upgrade-Insecure-Requests' => 1,
      'User-Agent' => 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36'
  ],
  //パラメータ指定
  'form_params' => [
    'email' => 'test@sample.com',
    'name'  => 'test'
  ]
];

$promises[] = $client->requestAsync('POST', 'https://sample.com/aaa.html', $config);
$response = \GuzzleHttp\Promise\all($promises)->wait();

メモリ節約版非同期リクエスト

<?php
    require_once(dirname(__FILE__) . '/vendor/autoload.php');

    use GuzzleHttp\Pool;
    use GuzzleHttp\Client;
    use GuzzleHttp\Psr7\Request;

    $client = new Client();

    $urlList = [
      'https://sample.com/1.html',
      'https://sample.com/2.html',
      'https://sample.com/3.html',
      'https://sample.com/4.html',
      'https://sample.com/5.html',
      'https://sample.com/6.html',
      'https://sample.com/7.html',
      'https://sample.com/8.html',
      'https://sample.com/9.html',
      'https://sample.com/10.html'
    ];

    $requests = function ($urlList) use ($client) {
        foreach ($urlList as $url) {
            yield function() use ($client, $url) {
                return $client->requestAsync('GET', $url);
            };
        }
    };

    $contents = [];

    $pool = new Pool($client, $requests($urlList), [
        'concurrency' => 10,
        'fulfilled' => function ($response, $index) use ($urlList, &$contents) {
            $contents[$urlList[$index]] = [
              'html'             => $response->getBody()->getContents(),
              'status_code'      => $response->getStatusCode(),
              'response_header'  => $response->getHeaders()
            ];
        },
        'rejected' => function ($reason, $index) use ($urlList, &$contents) {
            // this is delivered each failed request
            $contents[$urlList[$index]] = [
              'html'   => '',
              'reason' => $reason
            ];
        },
    ]);

    $promise = $pool->promise();
    $promise->wait();

    var_dump($contents);
  • 簡易版で大量に非同期リクエストした場合、promiseオブジェクトにリクエスト数分状態を保持してしまうのでメモリオーバーする事がある
  • ジェネレータを使うと実際に必要になる(Poolで順次実行される時)までリクエストが実行されずメモリを消費しない

参考:
https://speakerdeck.com/suzuki/guzzle-promisewoshi-tuta-fei-tong-qi-chu-li-niyoruapikorufalsegao-su-hua
https://mike-neko.github.io/blog/guzzle/

35
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
34