Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 假装:根据响应状态重试_Java_Spring_Spring Cloud_Netflix Feign_Spring Cloud Netflix - Fatal编程技术网

Java 假装:根据响应状态重试

Java 假装:根据响应状态重试,java,spring,spring-cloud,netflix-feign,spring-cloud-netflix,Java,Spring,Spring Cloud,Netflix Feign,Spring Cloud Netflix,我目前正在使用SpringCloud和Faign在我的应用程序中使用微服务。由于在单个服务实例中可能会发生数据库连接等故障,使其返回500个HTTP状态代码,因此我希望确保服务的客户端重试下一个服务器。目前,当服务根本没有运行时,Ribbon的重试机制就像一个魔咒,但是当它收到500状态码时,仍然会立即返回错误,而不进行任何重试 如果实例返回500响应,是否可以将外部客户端或其底层功能区负载平衡器配置为重试下一台服务器 配置与此线程中的配置基本相同: 我很想使用Ribbons'HttpRespo

我目前正在使用SpringCloud和Faign在我的应用程序中使用微服务。由于在单个服务实例中可能会发生数据库连接等故障,使其返回500个HTTP状态代码,因此我希望确保服务的客户端重试下一个服务器。目前,当服务根本没有运行时,Ribbon的重试机制就像一个魔咒,但是当它收到500状态码时,仍然会立即返回错误,而不进行任何重试

如果实例返回500响应,是否可以将外部客户端或其底层功能区负载平衡器配置为重试下一台服务器

配置与此线程中的配置基本相同:


我很想使用Ribbons'HttpResponseEvalidator()之类的实现,但我找不到任何适用于Spring Cloud及其伪/Ribbon集成的实现。这个问题非常古老,解决方案可能已经找到,或者当时不可能找到。不管怎样,我认为这个答案可能仍然对某人有帮助。 请将此代码用作参考,此代码不用于生产。 外挂允许您配置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;
  }
}
公共静态类RetryOnScaleErrorDecoder实现ErrorDecoder{
@凌驾
公共异常解码(字符串方法键、响应){
FeignException异常=错误状态(methodKey,响应);
//这是一个糟糕的部分。请检查如何实现feign.codec.ErrorDecoder.RetryAfterDecoder,以便正确解析retry after标头
Collection headers=response.headers().get(“在之后重试”);
字符串repeatAfterString=“0”;
if(Objects.nonNull(头)){
repeatAfterString=Iterables.getFirst(头,“0”);
}
断言repeatAfterString!=null;
Date repeatAfter=新日期(currentTimeMillis());
if(repeatAfterString.matches(“^[0-9]+$”){
试一试{
long deltamilis=SECONDS.toMillis(long.parseLong(repeatAfterString));
repeatAfter=新日期(currentTimeMillis()+增量);
}捕获(忽略NumberFormatException){
//TODO:日志记录
}
}
//这是我们根据状态代码值决定重试的部分
if(exception.status()==429){
返回新的RetryableException(
response.status(),
异常。getMessage(),
response.request().httpMethod(),
例外情况,
重复
);
}
返回异常;
}
}
我认为与Ribbon一起使用会产生预期的效果