如何在Laravel中出现503错误时让Guzzle 6重试请求

时间:2016-02-08 22:33:27

标签: php http middleware guzzle6

我在Laravel 5.2中编写了一些代码来检索来自不可靠API源的结果。但是,它需要能够在失败的尝试时自动重试请求,因为API调用在大约三分之一的时间内导致503。

我使用Guzzle执行此操作,我想我知道在处理之前将拦截503响应的代码放在哪里;但我不确定在那里写什么。

guzzle文档提供的重试次数并不多,而我在Guzzle 6中遇到的所有示例都只显示了如何检索结果(我已经可以做到),但不知道如何获取结果如果需要,重复请求。

我绝不会要求任何人为我做这项工作 - 但我认为我正在接近我对此的理解。如果有人能指出我正确的方向,我们将不胜感激:)

修改

我会尝试修改。请考虑以下代码。在其中,我想发送一个通常应该产生JSON响应的GET请求。

DataController.php

$client = new \GuzzleHttp\Client();
$request = $client->request('GET', 'https://httpbin.org/status/503'); // URI is for testing purposes

当此请求的响应为503时,我可以在此处拦截它:

Handler.php

public function render($request, Exception $e)
{
  if ($e->getCode() == 503)
  {
    // Code that would tell Guzzle to retry the request 5 times with a 10s delay before failing completely
  }

  return parent::render($request, $e);
}

我不知道那是最好的地方,但真正的问题是我不知道在if ($e->getCode() == 503)内写什么

2 个答案:

答案 0 :(得分:2)

默认情况下Guzzle会在返回非2 **响应时抛出exceptions。在您的情况下,您会看到503响应。可以将异常视为应用程序可以从中恢复的错误。这种方式的工作方式是使用try catch块。

try {
    // The code that can throw an exception will go here
    throw new \Exception('A generic error');
    // code from here down won't be executed, because the exception was thrown.
} catch (\Exception $e) {
    // Handle the exception in the best manner possible.
}

您可以包含可能在块的try部分中引发异常的代码。然后在块的catch部分添加错误处理代码。您可以阅读上面的链接,了解有关php如何处理异常的更多信息。

对于你的情况,让我们在控制器中将Guzzle调用它自己的方法:

public function performLookUp($retryOnError = false)
{
    try {
        $client = new \GuzzleHttp\Client();
        $request = $client->request('GET', 'https://httpbin.org/status/503'); 
        return $request->send();
    } catch (\GuzzleHttp\Exception\BadResponseException $e) {
        if ($retryOnError) {
            return $this->performLookUp();
        }
        abort(503);
   }
}

现在,您可以在控制器中执行$this->performLookUp(true);

答案 1 :(得分:2)

只是添加一些信息来澄清Logan所做的几点。

Guzzle" can"在2 ** / 3 **以外的响应上抛出异常。这一切都取决于GuzzleHttp\HandlerStack的创建方式。

$stack = GuzzleHttp\HandlerStack::create();
$client = new Client(['handler'=> $stack]);

$client = new Client();
// These two methods of generating a client are functionally the same.


$stack = New GuzzleHttp\HandlerStack(new GuzzleHttp\Handler\CurlHandler());
$client = new Client(['handler'=> $stack]);
// This client will not throw exceptions, or perform any of the functions mentioned below.

create方法将默认处理程序添加到HandlerStack。解析HandlerStack后,处理程序将按以下顺序执行:

  1. 发送请求:
    1. http_errors - 发送请求时没有操作。在向堆栈返回响应承诺时,将在响应处理中检查响应状态代码。
    2. allow_redirects - 发送请求时无操作。在向堆栈返回响应承诺时发生重定向。
    3. cookies - 为请求添加Cookie。
    4. prepare_body - 将准备HTTP请求的正文(例如,添加内容长度,内容类型等默认标题。)
    5. 使用处理程序发送请求
  2. 处理回复:
    1. prepare_body - 没有关于响应处理的操作。
    2. cookies - 将响应cookie提取到cookie jar中。
    3. allow_redirects - 遵循重定向。 4.http_errors - 当响应状态代码> = 300时抛出异常。
  3. 如果没有提供$ handler参数,GuzzleHttp\HandlerStack::create()将根据系统上可用的扩展名选择最合适的处理程序。如Handler Documentation

    中所示

    通过手动创建GuzzleHttp\HandlerStack,您可以向应用程序添加中间件。鉴于您原始问题的背景"我如何重复请求"我相信你最感兴趣的是Guzzle 6.1中提供的Retry Middleware。这是一个中间件,它根据提供的决策函数的结果重试请求。

    文档还没有赶上这个课程。