Skip to content

Instantly share code, notes, and snippets.

@hirak
Created April 6, 2012 16:33
Show Gist options
  • Save hirak/2321179 to your computer and use it in GitHub Desktop.
Save hirak/2321179 to your computer and use it in GitHub Desktop.
curl_multiでHTTP非同期リクエストを行うサンプル ref: http://qiita.com/items/1c67b51040246efb4254
<?php
/**
* curl_multiでHTTP複数リクエストを並列実行するテンプレ
*
*/
//タイムアウト時間を決めておく
$TIMEOUT = 10; //10秒
/*
* 1) 準備
* - curl_multiハンドラを用意
* - 各リクエストに対応するcurlハンドラを用意
* リクエスト分だけ必要
* * レスポンスが必要な場合はRETURNTRANSFERオプションをtrueにしておくこと。
* - 全てcurl_multiハンドラに追加
*/
$mh = curl_multi_init();
$urls = array(
'http://localhost/sleep.php?wait=3',
'http://localhost/sleep.php?wait=2',
'http://localhost/sleep.php?wait=1',
);
foreach ($urls as $u) {
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $u,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $TIMEOUT,
CURLOPT_CONNECTTIMEOUT => $TIMEOUT,
));
curl_multi_add_handle($mh, $ch);
}
/*
* 2) リクエストを開始する
* - curl_multiでは即座に制御が戻る(レスポンスが返ってくるのを待たない)
* - いきなり失敗するケースを考えてエラー処理を書いておく
*/
$stat = curl_multi_exec($mh, $running); //multiリクエストスタート
if ( ! $running || $stat !== CURLM_OK) {
throw new RuntimeException('リクエストが開始出来なかった');
}
/*
* 3) レスポンスをcurl_multi_selectで待つ
* - 何かイベントがあったらループが進む
* selectはイベントが起きるまでCPUをほとんど消費せずsleep状態になる
* - どれか一つレスポンスが返ってきたらselectがsleepを中断して何か数字を返す。
*
*/
do switch (curl_multi_select($mh, $TIMEOUT)) { //イベントが発生するまでブロック
// ->最悪$TIMEOUT秒待ち続ける。タイムアウトは全体で統一しておくと無駄がない
case -1: //selectに失敗。通常は起きないはず…
case 0: //タイムアウト -> 必要に応じてエラー処理に入るべき
continue 2; //ここではcontinueでリトライします。
default: //どれかが成功 or 失敗した
$stat = curl_multi_exec($mh, $running); //ステータスを更新
do if ($raised = curl_multi_info_read($mh, $remains)) {
//変化のあったcurlハンドラを取得する
$info = curl_getinfo($raised['handle']);
echo "{$info['url']}: {$info['http_code']}\n";
$response = curl_multi_getcontent($raised['handle']);
if ($response === false) {
//エラー。404などが返ってきている
echo 'ERROR!!!', PHP_EOL;
} else {
//正常にレスポンス取得
echo $response, PHP_EOL;
}
curl_multi_remove_handle($mh, $raised['handle']);
curl_close($raised['handle']);
} while ($remains);
//select前に全ての処理が終わっていたりすると
//複数の結果が入っていることがあるのでループが必要
} while ($running);
echo 'finished', PHP_EOL;
curl_multi_close($mh);
<?php
/*
* セキュリティ的に問題のあるスクリプトなので実験以外では使わないでね。
*/
sleep((int)$_GET['wait']);
header('Content-Type: text/plain');
echo $_GET['wait'];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment