Curlは、ネットワークリクエストにPHPを使用する際の最も一般的なツールの1つです。特に、APIインターフェイスデータのプル、通知のプッシュ、複数のアドレスの検証などの大規模な並行性シナリオでは、多くの場合、 CURLが最初の選択です。そして、これらの慣行では、よく議論される質問は次のとおりです。
これは少しの詳細のように聞こえますが、高い並行性シナリオでは、この詳細があなたのプログラムが安定して実行できるかどうかの鍵になる可能性があります。
curl_close($ ch)は、 curl_init()によって初期化されたハンドル$ chを閉じるphpの関数です。簡単に言えば、関連するリソースをリリースします。多くのチュートリアルとドキュメントは、「それを使用した後に閉じることを忘れないでください」と強調します。
しかし、大規模な同時リクエストでは、リソースの頻繁な切り替えは本当に効率的ですか?
多くの開発者は、 curl_close()が呼び出される限り、メモリはすぐにシステムに「解放」されると誤って信じていますが、そうではありません。 PHPでは、特に長い接続スクリプトまたはSwoole/FPMの常駐メモリの場合、PHPのメモリ管理メカニズムはメモリをオペレーティングシステムにすぐに返さず、「利用可能」としてマークして次回待つことができます。
つまり、毎回curl_close()を呼び出す場合でも、スクリプトに数百または数千のcurl要求がある場合、特にリクエストが大量のデータを返す場合、メモリ使用量が増え続けることがあります。
以下は、説明する簡単な比較テストです。
// シーン1:呼ばれていません curl_close
for ($i = 0; $i < 1000; $i++) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.gitbox.net/test-endpoint?id=$i");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// 怠慢 curl_close
}
// シーン2:電話 curl_close
for ($i = 0; $i < 1000; $i++) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.gitbox.net/test-endpoint?id=$i");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
}
Memory_get_usage()の比較により、単一の実行スクリプトでは、2つの書き込み方法がメモリ使用量にほとんど違いがなく、違いさえ無視できることがわかりました。
ただし、複数のリクエストまたはSwoole Coroutinesを処理するFPMの下で長時間実行されているサービスでは、 curl_close()を呼び出すことなくメモリの連続バックログを引き起こし、最終的にOOMまたはパフォーマンスボトルネックをトリガーします。
同時リクエストの数が多い場合、curl_multiを使用することが正しいソリューションです。複数の同時リクエストを同時に初期化することができ、プロセスはポーリングメカニズムを通じて非同期に戻り、効率を改善し、リソースリリースをより適切に制御することができます。
$multiHandle = curl_multi_init();
$curlHandles = [];
for ($i = 0; $i < 100; $i++) {
$ch = curl_init("https://api.gitbox.net/batch?id=$i");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($multiHandle, $ch);
$curlHandles[$i] = $ch;
}
// 同時リクエストを実行します
do {
$status = curl_multi_exec($multiHandle, $active);
curl_multi_select($multiHandle);
} while ($active);
// 結果を取得して閉じます
foreach ($curlHandles as $ch) {
$response = curl_multi_getcontent($ch);
curl_multi_remove_handle($multiHandle, $ch);
curl_close($ch);
}
curl_multi_close($multiHandle);
結論は、特に短期間のスクリプトでは、 Curl_Close()自体がメモリを大幅に最適化することはできません。ただし、高い並行性、常駐メモリ、および長いライフサイクルサービスでは、 curl_close()を呼び出さないことは深刻なリソース漏れであり、最終的にはサービスの安定性を引き下げます。
したがって、それはパフォーマンスの最適化の「秘密」ではありませんが、プログラムが「あなたがそれを実行することができる」という前提です。
通常のバッチスクリプト:Curl + Curl_Closeをお勧めします
高い並行性処理:curl_multiを使用するか、Coroutineクライアント(Guzzle + Asyncなど)を使用します
長い接続サービス:curl_closeを含むリソースライフサイクルを必ず管理してください
PHP FPM:スクリプト内のリクエストのメモリ使用量に注意を払う、リクエストを合理的に分割するか、リクエストボリュームを制御する
詳細に直面してのみ、パフォーマンスは岩と同じくらい安定しています。次回、同時リクエストを書くときは、振り返ってCurl_close()を忘れているかどうかを確認することもできます。