Curlは、ネットワークリクエストにPHPを使用する際の最も一般的なツールの1つです。多くの開発者は、リクエストを完了した後、標準プロセスに従ってリソースを閉鎖します。つまり、 curl_close($ ch)を呼び出します。ただし、並行性やパフォーマンスの高い要件が高いシナリオでは、秘密の問題に遭遇します。Curl_Closeを呼び出した後、PHPスクリプトの実行に不合理な遅延があります。
この遅延は通常、長い接続(キープアライブ)または特定のサーバー構成のコンテキストで発生します。リクエストが完了したようですが、 Curl_Closeは実際に基礎となる接続のリリースプロセスを待っている可能性があるため、スクリプトの継続的な実行がブロックされます。
簡単な例を見てみましょう。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.gitbox.net/data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo "リクエストを完了します";
ほとんどの場合、このコードは迅速に実行できます。ただし、一部のサーバー環境では(特にターゲットサーバーがHTTP/2または接続マルチプレックスをサポートする場合)、 Curl_Closeは数百ミリ秒以上ブロックできます。
Curl_Closeは単にメモリを解放するだけでなく、特にHTTP Keep-Aliveが有効になっている場合、基礎となるTCP接続が閉じたり解放されたりするのを待つこともあります。この動作は、 Libcurlライブラリの新しいバージョンを使用する場合、または特定のサーバー(Nginx + Keep-Aliveなど)と通信する場合、より明白です。
さらに、 curl_execがデータを大きく返すか、接続が完全に読み取られていない場合、 curl_closeはバックグラウンドで残りのデータをクリーンアップしようとする場合があり、これにより実行時間がさらに増加します。
Curlopt_forbid_Reuseを設定して、接続の再利用によって引き起こされる遅延を回避することにより、接続を強制的に閉じることができます。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.gitbox.net/data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FORBID_REUSE, true); // 接続の再利用を無効にします
$response = curl_exec($ch);
curl_close($ch);
この方法は、いくつかのパフォーマンスを犠牲にします(リクエストごとに新しい接続が作成されるため)が、 curl_closeのブロック問題を効果的に回避できます。
簡単なGet Requestsを作成する必要があり、パフォーマンスに非常に心配している場合は、 FSOCCKOPENを使用して手動でリクエストを構築することを検討してください。したがって、CURLのリソース管理ロジックを完全にバイパスします。
SwooleやReactPhpなどの非同期フレームワークを使用している場合、Curlを非同期タスクとしてカプセル化し、バックグラウンドでリリース操作を実行して、メインスレッドのブロックを避けることができます。
多数のリクエストでは、 curl_multi_*インターフェイスを使用して接続を均一に管理し、頻繁な作成とハンドルの破壊を回避し、それによりcurl_closeのオーバーヘッドを削減できます。しかし、これは高度な使用法であり、SDKまたは基礎となるライブラリの構築に適しています。
curl_closeはハンドルを閉じるための単なる操作のようですが、いくつかのシナリオでパフォーマンスのボトルネックになる可能性があります。 Curlオプションを合理的に設定するか、実際のニーズに応じて他のネットワーク要求方法を選択することにより、 Curl_Closeによって引き起こされる不必要な遅延を効果的に回避できます。パフォーマンスに敏感なPHPプロジェクトでは、これらの詳細に焦点を当てることで、ユーザーエクスペリエンスとより高いシステムスループットにつながることがよくあります。