PHPでは、 curl_multi_*一連の関数を使用すると、複数のHTTP要求を同時に送信し、プログラムの実行効率を大幅に改善できます。ただし、多くの人がcurl_multi_closeを使用してマルチレクエストセッションを終了する場合、重要な問題を無視する傾向があります。
タイムアウト時間が合理的に制御されていない場合、リクエストが長期にわたって反応しない場合、アプリケーション全体が立ち往生し、非常に悪いユーザーエクスペリエンスになります。この記事では、例を使用して、 curl_multi_closeを使用するときにタイムアウトコントロールをエレガントに実装する方法を教えます。
実際、 curl_multi_closeはcurl_multiハンドルを閉じるためにのみ使用され、タイムアウト自体を制御しません。実際のタイムアウトコントロールは、リクエストを実行する段階で発生する必要があります(つまり、 curl_multi_execおよびcurl_multi_select )。
簡単に言えば、タイムアウト制御は以下に依存します。
単一のカールハンドルにタイムアウトを設定します
実行ループの合計時間を記録して判断します
これが実用的な例です。 https://gitbox.net/api/endpoint1およびhttps://gitbox.net/api/endpoint2を要求する2つのリクエストがあるとします。すべてのリクエストに合計10秒以上かかることはないと思います。
<?php
// 2つを作成します cURL ハンドル
$ch1 = curl_init('https://gitbox.net/api/endpoint1');
$ch2 = curl_init('https://gitbox.net/api/endpoint2');
// 各リクエストのタイムアウトを個別に設定します(オプション)
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_TIMEOUT, 8); // 1人あたりのほとんどのリクエスト82番
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_TIMEOUT, 8);
// aを作成します cURL 批处理ハンドル
$mh = curl_multi_init();
// 添加ハンドル到批处理ハンドル中
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
// バッチ処理を実行します
$startTime = microtime(true);
$timeout = 10; // 合計タイムアウト(2番)
do {
$status = curl_multi_exec($mh, $active);
// まだアクティブな接続がある場合
if ($active) {
// ブロッキングと待機
$n = curl_multi_select($mh, 1.0);
// もし select 戻る -1,忙しいのは避けてください
if ($n === -1) {
usleep(100000); // 寝る100毫2番
}
}
// タイムアウトかどうかを確認してください
if ((microtime(true) - $startTime) > $timeout) {
echo "要求する合計時間は超えています{$timeout}2番,強制中断。\n";
break;
}
} while ($active && $status == CURLM_OK);
// 結果を読んでください
$response1 = curl_multi_getcontent($ch1);
$response2 = curl_multi_getcontent($ch2);
// 关闭ハンドル
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
curl_close($ch1);
curl_close($ch2);
// 結果を印刷します
echo "Response 1: " . substr($response1, 0, 100) . "...\n";
echo "Response 2: " . substr($response2, 0, 100) . "...\n";
?>
curlopt_timeout単一のリクエストのタイムアウトを制御します。
MicroTime(True)を記録することにより、総実行時間は手動で制御されます。
curl_multi_selectを使用する場合、過度のCPU使用を避けるために、適切なタイムアウト値(1秒など)を設定します。
curl_multi_closeはリソースのクリーニングのみを担当し、タイムアウトロジックを制御しません。
SELECT TIMEOT(たとえば、0.01秒)を短すぎると、システムの負荷が増加する可能性があります。
curl_multi_selectが-1を返す場合、それは待機するファイル記述子がなく、忙しいループを避けるために適切な睡眠( USLEEP )が必要です。
タイムアウトが発生した場合、リソースの漏れを避けるために、未完成のリクエストを積極的にキャンセルすることが最善です。