伪装:根据响应状态重试 [英] Feign: Retry depending on response status
问题描述
我目前正在使用Spring Cloud和Feign在我的应用程序中使用微服务.由于可能发生,因此在单个服务实例中数据库连接等将失败,从而使其返回500 HTTP状态代码,因此我想确保该服务的客户端重试下一个服务器.当前,Ribbon的重试机制在服务完全不运行时就像一个超级按钮,但是当它收到500状态代码而没有任何重试时,它仍然会立即返回错误.
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 instance, making it return 500 HTTP status code, I want to make sure, that the next server is retried by the service's clients. Currently, Ribbon's retry mechanism works like a charm when the service is not running at all, however it still returns instantly an error when it receives a 500 status code, without any retry.
如果实例返回500响应,是否可以将Feign客户端或它们的基础Ribbon负载均衡器配置为重试下一个服务器?
Is it possible to configure the Feign clients or their underlying Ribbon load balancers to retry the next server, if an instance returns a 500 response?
该配置与该线程中的几乎相同:是伪装重试需要某种配置吗?
The configuration is pretty much the same as in this thread: Does Feign retry require some sort of configuration?
我很想使用Ribbons的HttpResponseValidator(
I would love to use an implementation like Ribbons' HttpResponseValidator (https://github.com/Netflix/ribbon/blob/master/ribbon/src/main/java/com/netflix/ribbon/http/HttpResponseValidator.java), but I couldn't find anything usable for Spring Cloud and its Feign/Ribbon integration
推荐答案
这个问题很老,解决方案可能已经找到或当时无法解决.无论如何,我认为答案仍然可以帮助某人8). 请以此为参考,此代码不适用于生产. Feign允许您配置errorDecoder-这是发生魔术的地方.
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())
这里是实现,我使用该类在服务扩展时从AWS从HTTP错误429重试请求
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<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结合使用将产生预期的结果.
I think that in conjunction with Ribbon it will produce desired result.
这篇关于伪装:根据响应状态重试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!