Guzzleで非同期の並列リクエストを行う
Oct 29, 2016 · serverphp
PHP
のHTTPクライアント(Guzzle)で非同期の並列リクエストを行う方法
Guzzle
は内部ではcurl
を使っており、便利なcurl
を面倒な設定をせずに使えるというありがたいもの
(なおcurl
がなくても動くがその場合は非同期が使えないなど機能が制限されるらしい)
事前準備
動作環境は以下のとおり
- PHP 5.5.0以上
- curl 7.19.4以上 (要openSSL/zlib)
インストール
composer
でguzzlehttp/guzzle
を入れる
(guzzle/guzzle
は古いバージョンなので注意)composer
を使っているので、使う時はrequire 'vendor/autoload.php';
を忘れないこと
php.iniの設定
allow_url_fopen = ON
を設定しておく
使い方
複数のURLに並列に非同期にリクエストをかける方法は以下のとおり
まずは、$requests
に実際のリクエストを生成する処理をクロージャとして登録する。
今回であれば、URLのリストから単純にURLを取り出し、$client->getAsync($url)
としてリクエストを生成している
(URLのエンドポイントだけが違うような場合はbase_uri
を指定した方がスマート)
ポイントはyield
でジェネレータを使っていること。
通常はforeach
をした時点でそのループの回数分中の処理が実行されてメモリなどのリソースを消費するが、
ジェネレータを使うと実際に必要になる(今回であればPool
で順次実行される時)まで実行されずリソースを消費しないメリットがある
リクエストの生成処理ができれば、Pool
オブジェクトに渡してPromise
を生成する。
その際、concurrency
で同時リクエスト数を、fulfilled
で成功時の処理、rejected
で失敗時の処理が行われる。
非同期の場合、リクエストは生成順に実行されるが、当然、処理結果は順不同で返ってくる。
ちなみにPromise
のwait()
の部分で全ての並列処理が終わるまで待機される。
これを忘れると完了しないまま処理が終わってしまう
つまり、例えばあるページにアクセスした時にバックグラウンドの非同期でダウンロードを行うといったことはできない。
そういったことをしたい場合は、Laravel
のキューなんかがおすすめ
小ネタ
$client = new Client(['debug' => true]);
としておくと細かな通信状況が出力されるので便利
参考リンク
開発環境
- PHP 5.6
- Guzzle 6.2.2