【问题标题】:Feign: Retry depending on response statusFeign:根据响应状态重试
【发布时间】:2016-10-03 12:13:58
【问题描述】:
【问题讨论】:
标签:
java
spring
spring-cloud
netflix-feign
spring-cloud-netflix
【解决方案1】:
这个问题很老了,可能已经找到了解决方案,或者当时不可能。无论如何,我认为这个答案可能仍然对某人有帮助 8 )。
请将此作为参考,此代码不用于生产用途。
Feign 允许你配置 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;
}
}
我认为与 Ribbon 结合使用会产生预期的效果。