5

まとめ

そのタイトルのとおり、Guzzle ではドキュメントにあるように、時間を節約するために一度に複数のリクエストを送信できます。

$responses = $client->send(array(
    $requestObj1,
    $requestObj2,
    ...
));

(given that each request object is an instance of
Guzzle\Http\Message\EntityEnclosingRequestInterface)

応答が戻ってきたら、どの応答がどの要求に対するものかを識別するために、各要求をループして応答を取得できます (上記のコマンドを実行した後にのみ利用可能)。

$response1 = $requestObj1->getResponse();
$response2 = $requestObj2->getResponse();
...

B. 問題

リクエスト オブジェクトに同じデータが含まれている場合。元のリクエストを特定することは不可能です。

2 つの記事を作成する必要がある次のシナリオがあると仮定します: A と B の距離サーバー: something.com/articles/create.json

各リクエストには同じ POST データがあります。

subject: This is a test article

作成後、2 つの場所を含む Guzzle 応答が返されます。

something.com/articles/223.json
something.com/articles/245.json

上記の方法を使用して応答とその要求をリンクしても、要求オブジェクトがまったく同じであるため、どの応答がどの記事に対するものかはまだわかりません。

したがって、私のデータベースでは、結果を書き留めることができません。

article A -> Location: 245.json
article B -> Location: 223.json

それは逆になる可能性があるためです。

article A -> Location: 223.json
article B -> Location: 245.json

解決策は、POST リクエストに追加のパラメータを追加することです。

subject: This is a test article
record: A

しかし、距離サーバーはキー「レコード」を理解していないため、エラーを返し、記事を作成しません。距離サーバーはサードパーティのサーバーであり、その動作方法を変更することはできません。

これに対する別の適切な解決策は、リクエスト オブジェクトに特定の ID/タグを設定することです。これにより、後で識別できます。ただし、ドキュメントに目を通しましたが、次のようなリクエストを一意に識別する方法はありません

$request->setID("id1")

or

$request->setTag("id1")

これは何ヶ月も私を悩ませてきましたが、まだこの問題を解決できません.

解決策がある場合は、お知らせください。

どうもありがとう、そしてあなたは私を救ってくれました!!!!

この長い投稿を読んでくれてありがとう。

4

6 に答える 6

1

私ははるかに良い答えを見つけました。

ドキュメントのように、一度に 20 個のリクエストのバッチを送信し、同時に 4 個のリクエストを送信し、プーリング手法を使用して満たされ、拒否されました。

配列を生成/構築するときに、このコードを requestAsync() 関数呼び出しの最後に追加できることがわかりました(両方を別の場所で行います)。

$request = $request->then(function (\GuzzleHttp\Psr7\Response $response) use ($source_db_object) {
            $response->_source_object = $source_db_object;
            return $response;
});

そして、プールのクローズでは、応答の _source_object に通常どおりアクセスでき、うまく機能します。少しハックだと思いますが、Guzzle で絶対に衝突しない名前を使用することが確実な場合は、これで問題ありません。

完全な例を次に示します。

use GuzzleHttp\Client;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Response as GuzzleResponse;

$client = new Client();
$requests = [];

// Simple set-up here, generate some random async requests
for ($i = 0; $i < 10; $i++) {
    $request = $client->requestAsync('GET', 'https://jsonplaceholder.typicode.com/todos/1');
    // Here we can attach any identifiable data
    $request->_source_object = $i;
    array_push($requests, $request);
}

$generator = function () use($requests) {
    while ($request = array_pop($requests)) {
        yield function() use ($request) {
            return $request->then(function (GuzzleResponse $response) use ($request) {
                // Attach _source_object from request to the response
                $response->_source_object = $request->_source_object ?? [];

                return $response;
            });
        };
    }
};

$requestPool = new Pool($client, $generator(), [
    'concurrency' => 5,
    'fulfilled' => function ($response) {
        // Then we can properly access the _source_object data once response has arrived here!
        echo $response->_source_object . "\n";
    }
]);

$requestPool->promise()->wait();
于 2016-06-29T20:31:33.507 に答える
0

新しい GuzzleHttp guzzlehttp/ guzzle に関連する更新

同時/並列呼び出しは、Promise を含むいくつかの異なる方法で実行されるようになりました..同時リクエスト

RequestInterfaces の配列を渡す古い方法は機能しなくなります。

ここで例を参照してください

    $newClient = new  \GuzzleHttp\Client(['base_uri' => $base]);
    foreach($documents->documents as $doc){

        $params = [
            'language' =>'eng',
            'text' => $doc->summary,
            'apikey' => $key
        ];

        $requestArr[$doc->reference] = $newClient->getAsync( '/1/api/sync/analyze/v1?' . http_build_query( $params) );
    }

    $time_start = microtime(true);
    $responses = \GuzzleHttp\Promise\unwrap($requestArr); //$newClient->send( $requestArr );
    $time_end = microtime(true);
    $this->get('logger')->error(' NewsPerf Dev: took ' . ($time_end - $time_start) );

この例では、 $requestArr[$doc->reference]を使用して各レスポンスを参照できます。つまり、配列にインデックスを付けて、Promise::unwrap 呼び出しを実行します。

于 2015-09-23T23:21:56.133 に答える
0

私はこのようにします:

// create your requests
$requests[] = $client->createRequest('GET', '/endpoint', ['config' => ['order_id' => 123]]);
...
// in your success callback get 
$id = $event->getRequest()->getConfig()['order_id']
于 2015-05-13T10:10:01.293 に答える
0

私もこの問題に遭遇しました。最初に上がったスレッドです。これが解決済みのスレッドであることはわかっていますが、最終的にはより良い解決策を思いつきました。これは、この問題に遭遇する可能性のあるすべての人を対象としています。

オプションの 1 つは、Guzzle Pool::batch を使用することです。

バッチが行うことは、プールされたリクエストの結果を配列にプッシュし、配列を返すことです。これにより、応答と要求が同じ順序になります。

$client = new Client();

// Create the requests
$requests = function ($total) use($client) {
    for ($i = 1; $i <= $total; $i++) {
        yield new Request('GET', 'http://www.example.com/foo' . $i);
    }
};

// Use the Pool::batch()
$pool_batch = Pool::batch($client, $requests(5));
foreach ($pool_batch as $pool => $res) {

    if ($res instanceof RequestException) {
         // Do sth
        continue;
    }

    // Do sth
}
于 2019-08-01T05:54:05.940 に答える