虚假客户端使您可以轻松地基于您已经知道的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
如何处理错误是最重要的事情,因为如果有错误,您将不会将明智的回应返回给客户,并且在出现问题时也可以轻松进行调查。 我认为明智的做法是:
- 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