PHPでは、 curl_multi_*一連の関数は、通常、 curl_multi_add_handleおよびcurl_multi_execと併用される非同期的に同時リクエストに能力を提供します。 curl_multi_add_handleを使用して複数のcurlハンドルをマルチハンドルに追加すると、 curl_multi_remove_handleは、リクエストが完了した後、各ハンドルから各ハンドルをマルチハンドルから削除できます。
$multiCurl = curl_multi_init();
$curlHandles = [];
// 複数を追加しますcurlハンドルmultiハンドルに
for ($i = 0; $i < 5; $i++) {
$curlHandles[$i] = curl_init("http://gitbox.net/api/data$i");
curl_multi_add_handle($multiCurl, $curlHandles[$i]);
}
// リクエストを実行します
do {
$status = curl_multi_exec($multiCurl, $active);
} while ($active);
// 各ハンドルを取り外します
foreach ($curlHandles as $ch) {
curl_multi_remove_handle($multiCurl, $ch);
curl_close($ch);
}
curl_multi_close($multiCurl);
上記のコードでは、 curl_multi_remove_handleを介して各curlハンドルを削除します。リソースが正しくリリースされることを保証しますが、ループ内のcurl_multi_remove_handleへの頻繁な呼び出しは、特にリクエストの数が多い場合は、パフォーマンスオーバーヘッドが発生する可能性があります。
curl_multi_remove_handleを呼び出すとき、PHPは下部のマルチハンドルの状態を更新する必要があります。これは、特に同時リクエストの数が多い場合、比較的時間がかかる操作です。各リクエストが完了すると、ハンドルが削除されると、PHPはマルチスレッドのステータス情報を処理および更新する必要があります。ハンドルを頻繁に削除すると、次のパフォーマンスの問題が発生する可能性があります。
頻繁なメモリ管理:ハンドルを削除するとき、基礎となるメモリ管理メカニズムはリソースを再配分する必要があり、その結果、メモリの割り当てとリリースのオーバーヘッドが得られます。
ロックとスレッドの同期: curl_multi_remove_handleには、並行して要求するときにスレッドロック操作が含まれます。頻繁に電話がかかる可能性があり、競争のロックにつながり、実行効率をさらに低下させる可能性があります。
コールスタックの複雑さ:各コールは、特に高い並行性でスタックの深さを増加させます。ここでは、コールスタックの増加が全体的なパフォーマンスに影響を与える可能性があります。
したがって、これらの操作を最適化することは、特に頻繁な同時リクエストが必要な場合、パフォーマンスを改善するために非常に重要です。
各リクエストが完了した直後にcurl_multi_remove_handleを呼び出す代わりに、すべてのリクエストが完了した後、ハンドルを均一に削除できます。これにより、頻繁にリソースの更新を回避し、パフォーマンスの損失を減らすことができます。
$multiCurl = curl_multi_init();
$curlHandles = [];
// 複数を追加しますcurlハンドル
for ($i = 0; $i < 5; $i++) {
$curlHandles[$i] = curl_init("http://gitbox.net/api/data$i");
curl_multi_add_handle($multiCurl, $curlHandles[$i]);
}
// 同時リクエストを実行します
do {
$status = curl_multi_exec($multiCurl, $active);
} while ($active);
// 统一移除所有ハンドル
foreach ($curlHandles as $ch) {
curl_multi_remove_handle($multiCurl, $ch);
curl_close($ch);
}
curl_multi_close($multiCurl);
すべての要求が完了した後、ハンドルを均一に削除することにより、不必要な中間操作を削減し、パフォーマンスを改善できます。
いくつかのシナリオでは、同時リクエストの数を調整することにより、 curl_multi_remove_handleへの呼び出し数を減らすことができます。たとえば、すべてのリクエストのバッチ処理を行い、バッチの完了に応じてハンドルを均一に削除します。
$multiCurl = curl_multi_init();
$curlHandles = [];
// 1つの処理を想定します10リクエスト
$batchSize = 10;
for ($i = 0; $i < 100; $i++) {
$curlHandles[$i] = curl_init("http://gitbox.net/api/data$i");
curl_multi_add_handle($multiCurl, $curlHandles[$i]);
if (count($curlHandles) == $batchSize) {
// 同時リクエストを実行します
do {
$status = curl_multi_exec($multiCurl, $active);
} while ($active);
// 统一移除当前批次的所有ハンドル
foreach ($curlHandles as $ch) {
curl_multi_remove_handle($multiCurl, $ch);
curl_close($ch);
}
// 清空当前批次的ハンドル数组
$curlHandles = [];
}
}
// まだリクエストが残っている場合,処理を続けます
if (count($curlHandles) > 0) {
do {
$status = curl_multi_exec($multiCurl, $active);
} while ($active);
// 统一移除剩余ハンドル
foreach ($curlHandles as $ch) {
curl_multi_remove_handle($multiCurl, $ch);
curl_close($ch);
}
}
curl_multi_close($multiCurl);
リクエストのバッチ処理により、 curl_multi_remove_handleの呼び出し数を大幅に削減し、それによりパフォーマンスを向上させることができます。
場合によっては、同じAPI呼び出しを頻繁に行う場合は、HTTPの永続的な接続を有効にすることを検討する場合があります(Keep-Alive)。これにより、Curlは毎回新しい接続を確立するのではなく、同じ接続で複数回リクエストし、 curl_multi_remove_handleへの多くの接続と頻繁な呼び出しを減らします。
curlopt_forbid_reuseをtrueに設定して、各リクエストに新しい接続が使用されるようにすることにより、接続の再利用を無効にできます。接続の多重化を維持すると、通常、特別なニーズなしでパフォーマンスが向上します。
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Connection: keep-alive',
]);
接続を持続させることにより、接続の作成と破壊の頻度が減少し、パフォーマンスが向上します。
リクエストボリュームが非常に大きい場合、PHPカールが最良の選択ではない場合があります。この場合、 Guzzleなどの最新のHTTPクライアントを使用するなど、より高度な同時リクエストメソッドの使用を検討してください。通常、非常に同時リクエストを処理するときにパフォーマンスとメモリ管理が向上します。