Curl_multi_*シリーズ関数は、同時リクエストにPHPのCurl拡張機能を使用する場合、非常に重要なツールです。 curl_multi_closeは、 curlマルチハンドルを閉じる責任がありますが、不適切に使用すると、次のような異常な接続ステータスに簡単につながる可能性があります。一部のリクエストは完了せず、リソースが正しくリリースされず、不可解なタイムアウトが発生します。それでは、これらの例外を優雅かつ正しく回避するにはどうすればよいですか?この記事では詳細に説明します。
多くの開発者が同時リクエストを処理すると、コードは次のようになる場合があります。
<?php
$mh = curl_multi_init();
$ch1 = curl_init('https://gitbox.net/api/endpoint1');
$ch2 = curl_init('https://gitbox.net/api/endpoint2');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
// 開始して実行します
do {
$status = curl_multi_exec($mh, $active);
curl_multi_select($mh);
} while ($active && $status == CURLM_OK);
// 直接閉じます
curl_multi_close($mh);
この執筆方法の問題は、要求が完全に処理されていなくても(特にネットワーク条件が悪い場合)、 curl_multi_closeが直接呼び出され、いくつかの接続が大まかに終了することであり、その結果、状態の異常が自然に発生することです。
curl_multi_closeを呼び出す前に、すべてのハンドル( Curlハンドル)が処理され、それらが削除されていることを確認する必要があります!正しいプロセスは次のとおりです。
curl_multi_execは、すべてのリクエストが完了するまで繰り返し呼ばれます。
個々のCurlハンドル( curl_multi_remove_handle )を削除します。
単一のカールハンドル( curl_close )を個別に閉じます。
最後に、マルチハンドル( curl_multi_close )を閉じます。
変更されたコードの例は次のとおりです。
<?php
$mh = curl_multi_init();
$ch1 = curl_init('https://gitbox.net/api/endpoint1');
$ch2 = curl_init('https://gitbox.net/api/endpoint2');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
// 開始して実行します
do {
$status = curl_multi_exec($mh, $active);
if ($active) {
curl_multi_select($mh);
}
} while ($active && $status == CURLM_OK);
// シングルを取り外して閉じます handle
curl_multi_remove_handle($mh, $ch1);
curl_close($ch1);
curl_multi_remove_handle($mh, $ch2);
curl_close($ch2);
// 最後の終わり multi handle
curl_multi_close($mh);
curl_multi_remove_handleは、 curl_multi_closeの前に行う必要があります。
接続が要求に失敗した場合でも、 remove_handle +を介して正しくクリーニングする必要があります。
ループでcurl_multi_selectを使用すると、CPUの使用量を削減し、忙しい待機を避けることができます。
エラー( curl_errnoやcurl_errorなど)をキャッチしてみてください。また、成功するリクエストを盲目的に信頼しないでください。
高い並行性シナリオでは、詳細が成功または失敗を決定します。 curl_multi_closeの本質は、マルチハンドルを破壊することだけです。それ自体は、すべての単一の接続の安全な閉鎖を保証することはできません。したがって、マルチハンドルを閉じる前に、個々のハンドルを手動で削除して閉じてください。これは、接続ステータスの例外を回避するための鍵です。
正しい処理プロセスに従うことで、同時リクエストが、これらの頭痛の種が起きている隠されたバグから、安定して効率的に実行できるようになります。