11

HttpRequestPoolクラスは解決策を提供します 。これを指摘してくれた人々に感謝します。

簡単なチュートリアルはhttp://www.phptutorial.info/?HttpRequestPool-constructにあります。


問題

PHP で同時/並列/同時 HTTP リクエストを作成したいと思います。次のような連続したリクエストを避けたい:

  • 一連の要求が完了するまでに時間がかかりすぎます。リクエストが多いほど長くなる
  • セットの途中で 1 つのリクエストがタイムアウトすると、それ以降のリクエストが作成されない場合があります (スクリプトに実行時間制限がある場合)。

cURL を使用して PHP で同時に [sic] HTTP リクエストを作成する方法の詳細を見つけることができましたが、可能であればPHP のHTTP 関数を明示的に使用したいと考えています。

具体的には、データを一連の URL に同時に POST する必要があります。データが投稿される URL は、私の管理外です。それらはユーザー設定です。

応答を処理する前に、すべての要求が完了するのを待つ必要があるかどうかは気にしません。各リクエストに 30 秒のタイムアウトを設定し、リクエストが同時に行われた場合、すべてのリクエストが完了するまで最大 30 秒 (おそらくもう少し) 待たなければならないことがわかります。

これがどのように達成されるかについての詳細は見つかりません。しかし、私は最近、PHP5+ が同時 HTTP リクエストを処理できるという PHP のマニュアルで言及されていることに気付きました。

単一のリクエストの例 (正常に動作します)

<?php
$request_1 = new HttpRequest($url_1, HTTP_METH_POST);
$request_1->setRawPostData($dataSet_1);
$request_1->send();
?>

同時リクエストの例 (不完全、明確)

<?php
$request_1 = new HttpRequest($url_1, HTTP_METH_POST);
$request_1->setRawPostData($dataSet_1);

$request_2 = new HttpRequest($url_2, HTTP_METH_POST);
$request_2->setRawPostData($dataSet_2);

// ...

$request_N = new HttpRequest($url_N, HTTP_METH_POST);
$request_N->setRawPostData($dataSet_N);

// Do something to send() all requests at the same time
?>

どんな考えでも大歓迎です!

明確化 1 : PECL HTTP 関数に固執したい:

  • 彼らは素晴らしいOOPインターフェースを提供します
  • それらは問題のアプリケーションで広く使用されており、すでに使用されているものに固執することは、メンテナンスの観点から有益であるはずです
  • 一般に、cURL を使用する場合と比較して、PECL HTTP 関数を使用して HTTP 要求を行うために記述するコードの行数が少なくて済みます。コードの行数が少ないことは、メンテナンスの観点からも有益です。

明確化 2 : PHP の HTTP 関数が組み込まれていないことに気付きました。おそらく、間違った表現をしたので、訂正します。人々が余分なものをインストールしなければならないという心配はありません。これは配布されるアプリケーションではなく、それ自体がサーバーを持つ Web アプリケーションです。

明確化 3 : PECL HTTP はこれを行うことができないと誰かが正式に述べている場合、私は完全に満足しています。

4

6 に答える 6

10

HttpRequestPoolがあなたが探しているものだと私はかなり確信しています。

少し詳しく説明すると、フォークを使用して探しているものを実現できますが、これは不必要に複雑で、HTMLコンテキストではあまり役に立ちません。私はテストしていませんが、このコードは次のようになります。

//$requestsを送信するリクエストの配列とします
$ pool = new HttpRequestPool();
foreach($ requests as $ request){
  $ pool-> attach($ request);
}
$ pool-> send();
foreach($ pool as $ request){
  //何かをする
}
于 2008-10-12T22:53:38.477 に答える
2

HttpRequestPool(これはHttpの一部です)を試しましたか?リクエストオブジェクトをプールして機能させるようです。Httpが同時リクエストをサポートし、プールを除いて何も見つからないことをどこかで読んだことは知っています。

于 2008-10-10T10:37:42.687 に答える
2

私はかつて同様の問題を解決しなければなりませんでした: 応答時間を累積せずに複数のリクエストを実行しました。

ソリューションは、ノンブロッキングソケットを使用するカスタム ビルド関数になりました。次のように機能します。

$request_list = array(
  # address => http request string
  #
   '127.0.0.1' => "HTTP/1.1  GET /index.html\nServer: website.com\n\n",
   '192.169.2.3' => "HTTP/1.1 POST /form.dat\nForm-data: ...",
  );

foreach($request_list as $addr => $http_request) {
    # first, create a socket and fire request to every host
    $socklist[$addr] = socket_create();
    socket_set_nonblock($socklist[$addr]); # Make operation asynchronious

    if (! socket_connect($socklist[$addr], $addr, 80))
        trigger_error("Cannot connect to remote address");

    # the http header is send to this host
    socket_send($socklist[$addr], $http_request, strlen($http_request), MSG_EOF);
}

$results = array();

foreach(array_keys($socklist) as $host_ip) {
    # Now loop and read every socket until it is exhausted
    $str = socket_read($socklist[$host_ip], 512, PHP_NORMAL_READ);
    if ($str != "") 
        # add to previous string
        $result[$host_ip] .= $str;
    else
        # Done reading this socket, close it
        socket_close($socklist[$host_ip]);
}
# $results now contains an array with the full response (including http-headers)
# of every connected host.

socket_read は応答を待機せず、ソケット バッファがまだいっぱいでない場合に戻るため、サンク応答が半並列でフェッチされるため、はるかに高速です。

これを適切な OOP インターフェイスでラップできます。HTTP 要求文字列を自分で作成し、もちろんサーバー応答を処理する必要があります

于 2008-10-12T18:16:02.903 に答える
1

最近、友人が CurlObjects ( http://trac.curlobjects.com/trac ) を教えてくれました。これは、curl_multi を使用するのに非常に便利であることがわかりました。

$curlbase = new CurlBase; $curlbase->defaultOptions[ CURLOPT_TIMEOUT ] = 30; $curlbase->add( new HttpPost($url, array('name'=> 'value', 'a' => 'b'))); $curlbase->add( new HttpPost($url2, array('name'=> 'value', 'a' => 'b'))); $curlbase->add( new HttpPost($url3, array('name'=> 'value', 'a' => 'b'))); $curlbase->perform();

foreach($curlbase->requests as $request) { ... }

于 2009-02-08T21:20:34.263 に答える
0

PHPのHTTP関数も組み込まれていません。これらはPECL拡張機能です。あなたの懸念が人々が余分なものをインストールしなければならないことであるならば、両方の解決策は同じ問題を抱えています-そしてcURLは私が今までに行ったすべてのウェブホストにデフォルトで来るので、インストールされる可能性が高いと思います。

于 2008-10-03T21:54:12.123 に答える
-1

pcntl_fork()を使用して、リクエストごとに個別のプロセスを作成し、リクエストが終了するのを待つことができます。

http://www.php.net/manual/en/function.pcntl-fork.php

cURLを使いたくない理由はありますか?curl_multi_ *関数は、同時に複数のリクエストを許可します。

于 2008-10-03T21:39:14.617 に答える