6

我目前正在使用 Spring Cloud 和 Feign 在我的应用程序中使用微服务。由于它可能发生,数据库连接等在单个服务实例中失败,使其返回 500 HTTP 状态代码,我想确保下一个服务器由服务的客户端重试。目前,当服务根本没有运行时,Ribbon 的重试机制就像一个魅力,但是当它收到 500 状态码时,它仍然会立即返回错误,而无需任何重试。

如果实例返回 500 响应,是否可以配置 Feign 客户端或其底层 Ribbon 负载均衡器以重试下一个服务器?

配置与此线程中的配置几乎相同:Feign retry 是否需要某种配置?

我很想使用像 Ribbons 的 HttpResponseValidator (https://github.com/Netflix/ribbon/blob/master/ribbon/src/main/java/com/netflix/ribbon/http/HttpResponseValidator.java)这样的实现,但是我找不到任何可用于 Spring Cloud 及其 Feign/Ribbon 集成的东西

4

2 回答 2

2

这个问题很老了,当时可能已经找到了解决方案,或者当时不可能。无论如何,我认为这个答案可能仍然对某人有帮助 8 )。请将此作为参考,此代码不适用于生产用途。Feign 允许您配置 errorDecoder - 这是魔术发生的地方。

Feign.Builder builder = Feign.builder()
  .errorDecoder(new RetryOnScaleErrorDecoder())

这是实现,我使用该类在服务扩展时从 AWS 获得的 HTTP 错误 429 上重试请求

public static class RetryOnScaleErrorDecoder implements ErrorDecoder {

  @Override
  public Exception decode(String methodKey, Response response) {
    FeignException exception = errorStatus(methodKey, response);
    // This is a terrible part please check how feign.codec.ErrorDecoder.RetryAfterDecoder is implemented for proper parsing of retry-after header
    Collection<String> headers = response.headers().get("Retry-After");

    String repeatAfterString = "0";
    if (Objects.nonNull(headers)) {
      repeatAfterString = Iterables.getFirst(headers, "0");
    }

    assert repeatAfterString != null;

    Date repeatAfter = new Date(currentTimeMillis());

    if (repeatAfterString.matches("^[0-9]+$")) {
      try {
        long deltaMillis = SECONDS.toMillis(Long.parseLong(repeatAfterString));
        repeatAfter = new Date(currentTimeMillis() + deltaMillis);
      } catch (NumberFormatException ignored) {
        // TODO: logging
      }
    }
    // That's the part where we decide to retry based on status code value
    if (exception.status() == 429) {
      return new RetryableException(
          response.status(),
          exception.getMessage(),
          response.request().httpMethod(),
          exception,
          repeatAfter
      );
    }
    return exception;
  }
}

我认为与 Ribbon 结合使用会产生预期的结果。

于 2019-05-08T22:32:41.673 回答
0

试试这个配置:MY-SPRING-API.ribbon.retryableStatusCodes=404,500

这是同一个问题: Feign client and Spring retry

文件是: https ://docs.spring.io/spring-cloud-netflix/docs/2.2.10.RELEASE/reference/html/#retrying-failed-requests

于 2022-01-06T17:04:53.243 回答