首页 > 解决方案 > 使用 Guzzle 执行批处理请求

问题描述

我正在做一个项目,我需要使用 Guzzle 对端点执行 2000 个异步请求,并且每次我需要更改 url 参数中的 ID。

端点如下所示:http ://example.com/api/book?id=X

我尝试使用 for 循环来做到这一点,唯一的问题是它不是异步的。执行此类任务的更有效方法是什么?

public function fetchBooks () {
    $client = new Client();
    $responses = [];
    for ($i=1; $i < 2000; $i++) { 
        $response = $client->post('https://example.com/api/book?id=' . $i);
        array_push($responses, json_decode($response->getBody(), true));
    }
    return $responses;
}

标签: phplaravelguzzle

解决方案


在您的情况下,我将首先检查其余 api 是否公开了一个端点,这使得一次发送所有条目的数据成为可能。在这种情况下,如果允许附加的条目数量有限制,您将只需要一个调用,或者可能需要几个调用。

如果不是这样,那么没有其他办法,然后调用其余端点 2000 次。你已经说过了。您的调用是同步的,效率很低,因为它会等待每个请求完成,然后再开始下一个请求。

为避免这种情况,请改用异步函数$client->postAsync。这将使并发运行请求成为可能。每个请求都会返回一个承诺。基本上,您希望等待所有承诺解决并继续执行程序。为此,将所有承诺存储在一个数组中,并使用Promise\settle($promises)->wait();or Promise\unwrap($promises);,如果你想停止执行,以防出现错误。

代码可能如下所示:

<?php
use GuzzleHttp\Client;
use GuzzleHttp\Promise;

public function fetchBooks () {
    $client = new Client();
    $promises = [];
    for ($i=1; $i < 2000; $i++) { 
        $promise = $client->postAsync('https://example.com/api/book?id=' . $i);
        array_push($promises, $promise);
    }
    
    $results = Promise\settle($promises)->wait();
 
    $responses = [];

    foreach ($results as $result) {
      array_push($responses, json_decode($result->getBody(), true));
   }

   return $responses;
}


?>

推荐阅读