ホームページ > バックエンド開発 > PHPチュートリアル > PHPで同時リクエストを実装する方法(コード)

PHPで同時リクエストを実装する方法(コード)

不言
リリース: 2023-04-04 06:56:02
オリジナル
11306 人が閲覧しました

この記事の内容は、PHP で同時リクエスト (コード) を実装する方法に関するもので、一定の参考価値があります。必要な友人は参照してください。お役に立てば幸いです。

バックエンド サービス開発では、同時リクエストに対する要件がよくあります。たとえば、10 社のサプライヤー (それぞれが異なる url を提供している) の帯域幅データを取得する必要があります。統合を返します 最終的なデータをどうしますか?

PHP では、最も直感的な方法は、foreach urls を走査し、各リクエストの結果を保存することです。インターフェイスには平均 5 秒 かかり、このインターフェイスのリクエストには最大 50 秒 かかります。これは、速度とパフォーマンスを追求する Web サイトでは受け入れられません。

現時点では、同時リクエストが必要です。

PHPRequest

PHP は単一プロセス同期モデルであり、1 つのリクエストは 1 つのプロセス、I/O## に対応します。 # 同期がブロックされています。 nginx/apache/php-fpm などのサービスの拡張により、PHP は同時実行性の高いサービスを提供できます。原理はプロセス プールを維持することです。サービスが要求されるたびに、新しいプロセスが開始されます。各プロセスは独立して存在します。

PHP はマルチスレッド モードとコールバック処理をサポートしていないため、PHP 内部スクリプトは同期的にブロックされます。の場合、プログラムはリクエストが結果を返すまで I/O5s をブロックし、その後コードは実行を続けます。したがって、クローラーなどの同時実行性の高いリクエスト要件を実行することは非常に困難です。 では、同時リクエストの問題を解決するにはどうすればよいでしょうか?組み込みの file_get_contents

および

fsockopen リクエスト メソッドに加えて、PHP はリクエストを開始するための cURL 拡張機能もサポートしています。単一リクエスト: PHP cURL リクエストの詳細な説明と同時リクエストのサポート 同時実行の原則は cURL 拡張機能はマルチスレッドを使用して複数のリクエストを管理します。 PHP

同時リクエスト

コードを直接見てみましょうdemo

:

// 简单demo,默认支持为GET请求
public function multiRequest($urls) {
    $mh = curl_multi_init();
    $urlHandlers = [];
    $urlData = [];
    // 初始化多个请求句柄为一个
    foreach($urls as $value) {
        $ch = curl_init();
        $url = $value['url'];
        $url .= strpos($url, '?') ? '&' : '?';
        $params = $value['params'];
        $url .= is_array($params) ? http_build_query($params) : $params;
        curl_setopt($ch, CURLOPT_URL, $url);
        // 设置数据通过字符串返回,而不是直接输出
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $urlHandlers[] = $ch;
        curl_multi_add_handle($mh, $ch);
    }
    $active = null;
    // 检测操作的初始状态是否OK,CURLM_CALL_MULTI_PERFORM为常量值-1
    do {
        // 返回的$active是活跃连接的数量,$mrc是返回值,正常为0,异常为-1
        $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    // 如果还有活动的请求,同时操作状态OK,CURLM_OK为常量值0
    while ($active && $mrc == CURLM_OK) {
        // 持续查询状态并不利于处理任务,每50ms检查一次,此时释放CPU,降低机器负载
        usleep(50000);
        // 如果批处理句柄OK,重复检查操作状态直至OK。select返回值异常时为-1,正常为1(因为只有1个批处理句柄)
        if (curl_multi_select($mh) != -1) {
            do {
                $mrc = curl_multi_exec($mh, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }
    // 获取返回结果
    foreach($urlHandlers as $index => $ch) {
        $urlData[$index] = curl_multi_getcontent($ch);
        // 移除单个curl句柄
        curl_multi_remove_handle($mh, $ch);
    }
    curl_multi_close($mh);
    return $urlData;
}
ログイン後にコピー
この同時リクエストでは、まず、バッチ ハンドルを作成し、url の

cURL ハンドルをバッチ ハンドルに追加し、バッチ ハンドルの実行ステータスを継続的にクエリします。実行が完了したら、返された結果を取得します。 curl_multi

関連関数

/** 函数作用:返回一个新cURL批处理句柄
    @return resource 成功返回cURL批处理句柄,失败返回false
*/
resource curl_multi_init ( void )

/** 函数作用:向curl批处理会话中添加单独的curl句柄
    @param $mh 由curl_multi_init返回的批处理句柄
    @param $ch 由curl_init返回的cURL句柄
    @return resource 成功返回cURL批处理句柄,失败返回false
*/
int curl_multi_add_handle ( resource $mh , resource $ch )

/** 函数作用:运行当前 cURL 句柄的子连接
    @param $mh 由curl_multi_init返回的批处理句柄
    @param $still_running 一个用来判断操作是否仍在执行的标识的引用
    @return 一个定义于 cURL 预定义常量中的 cURL 代码
*/
int curl_multi_exec ( resource $mh , int &$still_running )

/** 函数作用:等待所有cURL批处理中的活动连接
    @param $mh 由curl_multi_init返回的批处理句柄
    @param $timeout 以秒为单位,等待响应的时间
    @return 成功时返回描述符集合中描述符的数量。失败时,select失败时返回-1,否则返回超时(从底层的select系统调用).
*/
int curl_multi_select ( resource $mh [, float $timeout = 1.0 ] )

/** 函数作用:移除cURL批处理句柄资源中的某个句柄资源
    说明:从给定的批处理句柄mh中移除ch句柄。当ch句柄被移除以后,仍然可以合法地用curl_exec()执行这个句柄。如果要移除的句柄正在被使用,则这个句柄涉及的所有传输任务会被中止。
    @param $mh 由curl_multi_init返回的批处理句柄
    @param $ch 由curl_init返回的cURL句柄
    @return 成功时返回0,失败时返回CURLM_XXX中的一个
*/
int curl_multi_remove_handle ( resource $mh , resource $ch )

/** 函数作用:关闭一组cURL句柄
    @param $mh 由curl_multi_init返回的批处理句柄
    @return void
*/
void curl_multi_close ( resource $mh )

/** 函数作用:如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流
    @param $ch 由curl_init返回的cURL句柄
    @return string 如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流。
*/
string curl_multi_getcontent ( resource $ch )
ログイン後にコピー
この例で使用される事前定義定数: CURLM_CALL_MULTI_PERFORM: (int) -1


CURLM_OK: (int) 0
PHP同時リクエストの消費時間の比較

最初のリクエストは上記の
    curl_multi_init## を使用します #メソッド、同時リクエストは
  1. 105

    回行われます。 2 番目のリクエストは従来の

    foreach
  2. メソッドを使用し、
  3. curl_init

    メソッド リクエストを使用して 105 回トラバースします。 #実際のリクエストに時間がかかる結果は次のとおりです:

excludePHPで同時リクエストを実装する方法(コード)download765ms

かかります。単純なリクエスト時間の最適化は

39.83/1.58 および 25 回に達しました。接続すると、さらに高くなるはずです。消費時間: オプション 1: 最も遅いインターフェイスは 1.58 秒に達しました

  • オプション 2: 平均消費時間105

    インターフェイスの数は
  • 384ms
  • このテストのリクエストは私の環境の内部インターフェイスであるため、消費時間は非常に短いです。クローラーリクエスト環境の最適化がより明確になります。 Note

    同時実行制限

curl_multi

は多くのシステム リソースを消費します。同時リクエストの数には特定のしきい値があり、通常は

512

CURL の内部制限により、最大同時実行数を超えるとエラーが発生します。 具体的なテスト結果は行っていません。他の人の記事を参照してください: Curl multi を使用するたびに、同時リクエストの数は適切ですか?タイムアウト時間サービス全体に影響を与えるため、CURLOPT_TIMEOUT

を設定してタイムアウトを制御し、一時停止されたリクエストによってプロセスが無期限にブロックされ、最終的にマシン サービスが強制終了されるのを防ぐことができます。

CPU全負荷

コード例では、同時実行ステータスのクエリを続けると、

cpu の負荷が高くなりすぎます。したがって、コードに usleep(50000);

ステートメントを追加する必要があります。

同時に、curl_multi_selectcpu の占有を制御することもできます。データが応答されるまで待機状態になります。起動され、次のように実行を継続します。新しいデータが到着するとすぐに、
CPU の不必要な消費が削減されます。 関連する推奨事項: AJAX キュー リクエストを実装する方法 (コード付き)

PHP は、curl_multi を使用して同時リクエストを実装しますメソッド例 php ヒント

以上がPHPで同時リクエストを実装する方法(コード)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート