【问题标题】:How can I get Guzzle 6 to retry a request upon a 503 error in Laravel如何让 Guzzle 6 在 Laravel 中出现 503 错误时重试请求
【发布时间】:2016-05-18 18:21:48
【问题描述】:

我在 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)里面写什么

【问题讨论】:

  • 您好,欢迎来到 SO。阅读 how to askmcve 以了解更受欢迎的问题。
  • 嗨,davejal,部分问题是,我不完全确定要写什么,但我试图更好地说明这个问题。如果这仍然没有帮助,请告诉我,我会再试一次。谢谢。

标签: php http middleware guzzle6


【解决方案1】:

默认情况下,当返回非 2** 响应时,Guzzle 会抛出 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);

【讨论】:

  • 感谢您的回复。不幸的是,我不得不在没有那个功能的情况下把我所拥有的东西交出来,但我会在下一次有机会的时候尝试完成它(为了知识起见)。所以我会尝试一下,让你知道它是怎么回事。再次感谢。
【解决方案2】:

只是添加一些信息以澄清 Logan 提出的几点。

Guzzle“可以”在 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 请求的正文(例如,添加 Content-Length、Content-Type 等默认标头)。
    5. 使用处理程序发送请求
  2. 处理响应:
    1. prepare_body - 对响应处理没有任何操作。
    2. cookies - 将响应 cookie 提取到 cookie jar 中。
    3. allow_redirects - 跟随重定向。 4.http_errors - 当响应状态码 >= 300 时抛出异常。

如果没有提供 $handler 参数,GuzzleHttp\HandlerStack::create() 将根据您系统上可用的扩展选择最合适的处理程序。如Handler Documentation中所示

通过手动创建您的GuzzleHttp\HandlerStack,您可以将中间件添加到应用程序中。鉴于您最初的问题“我如何重复请求”的上下文,我相信您对 Guzzle 6.1 中提供的Retry Middleware 最感兴趣。这是一个根据提供的决策函数的结果重试请求的中间件。

文档还没有赶上这个类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 2015-11-02
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    • 2018-06-03
    • 1970-01-01
    相关资源
    最近更新 更多