明智的Feign客户端配置

虚假客户端使您可以轻松地基于您已经知道的Spring注释编写静态客户端。 它还包括与其他netflix库的负载和良好的微服务模式(如服务发现,负载平衡和断路器)的集成。

Feign是可配置的,但是您通常需要先更改配置,然后再将其用于服务呼叫。

Logging

您将要查看正在发出什么请求。 这需要您做两件事:在application.yml中为虚拟配置设置loggerLevel,并将虚拟客户端类的日志记录级别设置为DEBUG。

logger.level:
  root: INFO 
  com.example.clients.InvoiceClient: DEBUG


feign:
  client:
    config:
      default:
        loggerLevel: basic

你可以设定loggerLevel至充分 if you want至see headers and response bodies in the logs too.

Whether to decode 404s

如果希望在客户端收到404 Not Found响应时引发FeignException,则可以将decode404设置为false,这是默认设置。 否则,如果将解码404设置为true,则会将null作为响应;如果将重播类型包装在“可选”中,则将收到“可选”。

Error decoder

如何处理错误是最重要的事情,因为如果有错误,您将不会将明智的回应返回给客户,并且在出现问题时也可以轻松进行调查。 我认为明智的做法是:

  1. retry on any server error (status > 499)重试用尽时返回相同的服务器错误在任何429上或设置了Retry-After标头后重试发生任何其他客户端错误时返回500使用状态记录错误,导致错误的方法以及响应正文

那是一个需求列表。 让我们构建一个满足以下条件的错误解码器:

public class CustomErrorDecoder implements ErrorDecoder {

    private static final Logger LOG = LoggerFactory.getLogger(CustomErrorDecoder.class);
    private ErrorDecoder defaultDecoder = new ErrorDecoder.Default();

    @Override
    public Exception decode(String methodKey, Response response) {
        //Requirement 5: log error first and include response body
        try {
            LOG.error("Got {} response from {}, response body: {}", response.status(), methodKey, IOUtils.toString(response.body().asReader()));
        } catch (IOException e) {
            LOG.error("Got {} response from {}, response body could not be read", response.status(), methodKey);
        }
        Exception defaultException = defaultDecoder.decode(methodKey, response);
        if (defaultException instanceof RetryableException.class) {
            //Requirement 3: retry when Retry-After header is set
            //Will be true if Retry-After header is set e.g. in case of 429 status
            return defaultException;
        }
        if (HttpStatus.valueOf(response.status()).is5xxServerError()) {
            //Requirement 1: retry on server error
            return new RetryableException("Server error", response.request().httpMethod(), new ServerErrorResponseFromOtherSystemException(HttpStatus.valueOf(response.status()), defaultException), null);
        } else {
            //Requirement 4: return 500 on client error
            return new ClientErrorResponseFromOtherSystemException("Client error " + response.status() + " from calling other system", defaultException);
        }
    }

}

并抛出异常:

//Requirement 4: return 500 on client error
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public class ClientErrorResponseFromOtherSystemException extends Exception {

    public ThirdPartyClientErrorResponseException(String message, Exception exception) {
        super(message, exception);
    }
}

public class ServerErrorResponseFromOtherSystemException extends Exception {
    private HttpStatus responseStatusFromOtherSystem;

    public ServerErrorResponseFromOtherSystemException(HttpStatus httpStatus, Exception exception) {
        this.responseStatusFromOtherSystem = httpStatus;
        super(message, exception);
    }

    public HttpStatus getStatus() {
        return responseStatusFromOtherSystem;
    }
}

的@ResponseStatus注解意味着当带注解的异常到达控制器时,spring将返回该状态。 确定响应状态ServerErrorResponseFromOtherSystemException我们需要控制器的异常处理程序:

@RestController
public class InvoiceController {

    //Handler methods

    @ExceptionHandler(ServerErrorResponseFromOtherSystemException.class)
    public void ResponseEntity handleServerErrorResponseException(ServerErrorResponseFromOtherSystemException ex) {
        //Requirement 2: return the same error when retry is exhausted
        return ResponseEntity.status(exception.getStatus()).build();
    }

}

为了伪装化重试器,它将需要作为Bean公开。 为了能够将异常传播策略设置为可展开,我们还需要使用我们的定制将虚假生成器公开为bean。 请参见下面的示例:

@Bean
public Retryer retryer() {
    return new Retryer.Default();
}

@Bean
public Feign.Builder feignBuilder(Retryer retryer) {
    return Feign.builder()
            .exceptionPropagationPolicy(ExceptionPropagationPolicy.UNWRAP)
            .errorDecoder(new ServerErrorRetryingErrorDecoder())
            .retryer(retryer);
}

将异常传播策略设置为可展开表示在内部RetryableException是当重试用尽时将抛出的异常,从而允许引发特定于应用程序的异常,然后由异常处理程序处理(同样,假设您使用的是Spring MVC)。

正确处理错误至关重要,从一开始就将其内置是一个好习惯-不要等待客户注意到第三方系统出现故障。 我发现,即使是最可靠的第三方系统,有时也会超时并返回502。这在我的生产环境中发生,发生了严重的网关错误,这在其他环境中从未见过。 幸运的是,我实现了此重试机制,并且重试了请求,并且在稍等一会儿之后,客户继续了旅程。

from: https://dev.to//philhardwick/sensible-feign-client-configuration-ma3

发布了0 篇原创文章 · 获赞 0 · 访问量 451

猜你喜欢

转载自blog.csdn.net/cunxiedian8614/article/details/105689841