Guzzleで非同期の並列リクエストを行う

PHPのHTTPクライアント(Guzzle)で非同期の並列リクエストを行う方法

Guzzleは内部ではcurlを使っており、便利なcurlを面倒な設定をせずに使えるというありがたいもの (なおcurlがなくても動くがその場合は非同期が使えないなど機能が制限されるらしい)

事前準備

動作環境は以下のとおり

インストール

php.iniの設定

allow_url_fopen = ON

を設定しておく

使い方

複数のURLに並列に非同期にリクエストをかける方法は以下のとおり

まずは、$requestsに実際のリクエストを生成する処理をクロージャとして登録する。
今回であれば、URLのリストから単純にURLを取り出し、$client->getAsync($url)としてリクエストを生成している
(URLのエンドポイントだけが違うような場合はbase_uriを指定した方がスマート)

ポイントはyieldでジェネレータを使っていること。
通常はforeachをした時点でそのループの回数分中の処理が実行されてメモリなどのリソースを消費するが、 ジェネレータを使うと実際に必要になる(今回であればPoolで順次実行される時)まで実行されずリソースを消費しないメリットがある

リクエストの生成処理ができれば、Poolオブジェクトに渡してPromiseを生成する。 その際、concurrencyで同時リクエスト数を、fulfilledで成功時の処理、rejectedで失敗時の処理が行われる。 非同期の場合、リクエストは生成順に実行されるが、当然、処理結果は順不同で返ってくる。

ちなみにPromisewait()の部分で全ての並列処理が終わるまで待機される。 これを忘れると完了しないまま処理が終わってしまう

つまり、例えばあるページにアクセスした時にバックグラウンドの非同期でダウンロードを行うといったことはできない。 そういったことをしたい場合は、Laravelキューなんかがおすすめ

小ネタ

$client = new Client(['debug' => true]);

としておくと細かな通信状況が出力されるので便利

参考リンク

開発環境