Multi-Request処理にPHPのCurl拡張機能を使用する場合、 curl_multi_*シリーズ関数は非常に重要です。特にcurl_multi_close 。ただし、多くの開発者は、実際のプロジェクトで無意識のうちにcurl_multi_closeを介したり誤って呼んだりすることが多く、パフォーマンスの劣化やリソースの無駄をもたらします。では、なぜ不必要なcurl_multi_closeコールを減らす必要があるのですか?より効率的にする方法は?
curl_multi_closeの主な機能は、 curl_multi_initによって作成されたマルチハンドルリソースを閉じることです。 curl_multi_closeが呼び出されるたびに、PHP基礎層は、それに関連するすべての内部状態のクリーンアップを含むリソースリリース操作を実行します。このオーバーヘッドは、小規模な要求については無視できるように思われるかもしれませんが、頻繁かつ意味のない作成とマルチハンドルリソースの閉鎖が高いと、大規模な要求環境は次の問題を引き起こす可能性があります。
パフォーマンスオーバーヘッド:各シャットダウンには、基礎となるシステムリソースのリリースと管理が含まれ、CPUとメモリの負担が増加します。
リソースの廃棄物:繰り返される創造と破壊は、プログラムが占めるメモリと接続リソースの大幅な変動につながります。
潜在的な安定性の問題:リソースの頻繁なリリースは、特にリクエストの数が大きい場合、接続エラー、要求の障害、その他の問題が発生する傾向がある場合に、トレースが困難な例外を引き起こす可能性があります。
並行性のパフォーマンスを削減する:頻繁なスイッチングリソースのため、処理速度が低下し、 CURL_MULTI_*を使用する当初の意図に違反します。
したがって、不必要なcurl_multi_closeコールを減らすと、アプリケーションの安定性と全体的なパフォーマンスが大幅に向上する可能性があります。
curl_multi_closeの使用を最適化するために、重要なのは、マルチハンドルリソースのライフサイクルを制御し、作成と破壊のタイミングを合理的に管理することです。ここにいくつかの実用的な最適化の提案があります:
論理的に許可する場合、同じマルチハンドルをマルチプレックスして、毎回1つを再作成する代わりに複数のリクエストを管理します。初期化フェーズ中にマルチハンドルを作成し、バッチにリクエストを追加し、バッチ実行後に均一に閉じることができます。
サンプルコード:
<?php
// 初期化 multi handle
$multiHandle = curl_multi_init();
$urls = [
'https://gitbox.net/api/user/1',
'https://gitbox.net/api/user/2',
'https://gitbox.net/api/user/3',
];
$curlHandles = [];
foreach ($urls as $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($multiHandle, $ch);
$curlHandles[] = $ch;
}
// すべてのリクエストを実行します
do {
$status = curl_multi_exec($multiHandle, $active);
curl_multi_select($multiHandle);
} while ($active);
// 結果を取得します
foreach ($curlHandles as $ch) {
$response = curl_multi_getcontent($ch);
echo $response . PHP_EOL;
curl_multi_remove_handle($multiHandle, $ch);
curl_close($ch);
}
// 最後にのみ閉じます multi handle
curl_multi_close($multiHandle);
?>
多くの開発者は、リクエストの小さなバッチが完了した後に習慣的にcurl_multi_closeを習得し、頻繁にスイッチングリソースにつながります。これを行うことは、すべてのバッチが完了した後、または合理的なバッチサイズ(100のリクエストのグループなど)で中央で処理された後、すべてのバッチを均一に閉じることです。
アプリケーションが複数のリクエストを開始する必要がある場合は、マルチハンドルのライフサイクルを管理するために、接続プールまたは専用のマルチカールマネージャークラスの使用を検討してください。
簡単な例:
<?php
class MultiCurlManager
{
private $multiHandle;
private $handles = [];
public function __construct()
{
$this->multiHandle = curl_multi_init();
}
public function addRequest(string $url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($this->multiHandle, $ch);
$this->handles[] = $ch;
}
public function execute()
{
do {
$status = curl_multi_exec($this->multiHandle, $active);
curl_multi_select($this->multiHandle);
} while ($active);
$responses = [];
foreach ($this->handles as $ch) {
$responses[] = curl_multi_getcontent($ch);
curl_multi_remove_handle($this->multiHandle, $ch);
curl_close($ch);
}
return $responses;
}
public function __destruct()
{
curl_multi_close($this->multiHandle);
}
}
// 使用
$manager = new MultiCurlManager();
$manager->addRequest('https://gitbox.net/api/data1');
$manager->addRequest('https://gitbox.net/api/data2');
$manager->addRequest('https://gitbox.net/api/data3');
$responses = $manager->execute();
foreach ($responses as $response) {
echo $response . PHP_EOL;
}
?>
この方法では、ライフサイクルを自動的に管理し、逃したリソースまたは逃したリソースを防ぐことができます。
curl_multi_closeは必要なリソースクリーニングステップですが、不合理または頻繁な呼び出しは実際にシステムのパフォーマンスをドラッグダウンします。マルチハンドルをマルチプレックスしたり、バッチクロージャーのタイミングを合理的に管理したり、接続プール管理の導入により、マルチレクエスト処理の効率と安定性を大幅に改善できます。
実際の開発では、これらの詳細に注意を払うことで、高い同時HTTPリクエストを処理する際にPHPアプリケーションがより快適になります。