【问题标题】:loop send request many time with Guzzle PHP使用 Guzzle PHP 循环发送请求多次
【发布时间】:2019-07-11 15:15:19
【问题描述】:

我有 400 条记录要通过调用服务器上的 Web 服务插入到数据库服务器。但是当我通过调用网络服务循环插入时,我得到了一个错误:

致命错误:未捕获的 GuzzleHttp\Exception\ClientException:客户端 错误 429 请求过多

我试试这个代码:

$http =  new \GuzzleHttp\Client();
        foreach ($data as $key => $value) {
            $response = $http->post('http://192.168.1.33/APIServer/public/api/data', [
            'form_params' => $value,
            ]); 
        }

我循环的所有记录都是 400 行。如何通过使用 Guzzle 调用该 Web 服务来插入所有记录。先谢谢了。

【问题讨论】:

  • 如果您发送数据的服务器没有批量插入端点,您可以在循环中添加等待函数以在请求之间产生一些延迟。
  • @AndriiFilenko 请创建答案。

标签: php laravel guzzle


【解决方案1】:

如果您发送数据的服务器没有批量插入端点,您可以在循环中添加wait 函数以在请求之间产生一些延迟。

【讨论】:

    【解决方案2】:

    GuzzleHttp 客户端根据服务器发送的响应码抛出异常。在您的情况下,第 3 方在一定数量的请求后向您发送带有 429 状态代码的响应。然后GuzzleHttp\Exception\ClientException 将其退回。

    要解决这个问题,您可以使用延迟的排队作业,创建一个作业SendApiRequest

    <?php
    
    namespace App\Jobs;
    
    use App\Jobs\Job;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    
    class SendApiRequest extends Job implements ShouldQueue
    {
        use InteractsWithQueue, SerializesModels;
    
        /**
         * \GuzzleHttp\Client
         */
        private $http;
    
        /**
         * Data array
         */
        private $data;
    
        /**
         * Url string
         */
        private $url = 'http://192.168.1.33/APIServer/public/api/data';
    
        /**
         * Create a new job instance.
         */
        public function __construct(Client $http, array $data)
        {
            $this->http = $http;
            $this->data = $data;
    
        }
    
        /**
         * Create a new peerreview
         *
         * @return void
         */
        public function handle()
        {
            $response = $this->http->post($this->url, $data);
    
            return $response;
        }
    }
    

    然后您可以使用延迟作业队列调用 api(假设第 3 方最多允许每分钟 60 个请求:

    $rateLimitPerMinute  = 60; 
    $http =  new \GuzzleHttp\Client();
    
    $counter = 1;
    foreach ($data as $key => $value) {
    
        $delayInMinutes = intval($counter/$rateLimitPerMinute);
    
        SendApiRequest::dispatch($http, $value)->delay(now()->addMinutes($delayInMinutes));
    
        $counter++;
    }
    

    另外,您可以在作业中获得响应后添加日志记录机制。存储这些数据很重要,以便您以后发现问题时可以参考。

    【讨论】:

    • PHP 怎么样,我应该更改哪个路径?
    • 相当肯定 OP 要求限制使用 Guzzle 使用远程 API 的速率,而不是在接收端。
    • 192.168.1.33 是您无法控制的 IP 吗?就像它的第 3 方 API 或您自己的服务器一样/
    • @MihirBhende 是的,我打电话给第三方
    • 我的错,我认为它在服务器上:让我更新我的答案。
    【解决方案3】:

    你可以做两件事:

    1. 将所有数据以批量方式发送一次请求调用,并在您的服务器端执行 foreach。所以你不需要在服务器上发送很多请求。

    2. 第二个是你可以remove request limit 从 Laravel 的那条路线上,这样你就可以按顺序发送许多请求

      为此,你可以关注这个:Disable rate limiter in Laravel?

    【讨论】:

    猜你喜欢
    • 2018-02-07
    • 2017-08-28
    • 2020-07-14
    • 2019-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-21
    • 1970-01-01
    相关资源
    最近更新 更多