Feign: Retry depending on response status

后端 未结 1 980
[愿得一人]
[愿得一人] 2021-02-10 04:53

I am currently using Spring Cloud and Feign to consume a Microservice in my application. Since it can happen, that a database connection or the like fails in a single service in

1条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-10 05:16

    This question is very old and the solution was probably already found or wasn't possible at the time. Anyway, I think that answer might still help someone 8 ). Please use this as a reference, this code is not intended for production use. Feign allows you to configure errorDecoder - this is the place where magic happens.

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

    Here is the implementation, I use that class to retry request on HTTP error 429 I get from AWS when service is scaling

    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 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;
      }
    }
    

    I think that in conjunction with Ribbon it will produce desired result.

    0 讨论(0)
提交回复
热议问题