OpenFeign提供了重试机制,重试次数针对的是客户端连接服务器的重试次数,官方文档中说:重试会对IO异常进行重试,比如:连接超时、读取超时。另外是RetryableException
抛出时会重试,这个异常可以在ErrorDecoder
中定义。
写在最前面
对于OpenFegin重试的触发一定是超过了Fegin或者Ribbon配置的connectTimeout和readTimeout时,才会生效。如果Hystrix配置的超时时间短了,则走的是Hystrix报的错,这样不会触发Retry
feign:
client:
config:
default:
connectTimeout: 1000
readTimeout: 1000
loggerLevel: BASIC
hystrix:
enabled: true
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 60000
feign:
client:
config:
default:
loggerLevel: BASIC
hystrix:
enabled: true
ribbon:
readTimeout: 1000
connectTimeout: 1000
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 60000
feign:
client:
config:
default:
loggerLevel: BASIC
hystrix:
enabled: true
ribbon:
readTimeout: 1000
connectTimeout: 1000
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 100
我想传达的意思就是,hystrix配置
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
一定要长于连接和读取超时之和,才会retry配置生效
配置方式
Retryer的配置方式无外乎:Yaml
和@Configuration
两种方式
1.Yaml方式
feign:
client:
config:
default:
retryer: feign.Retryer.Default
loggerLevel: BASIC
hystrix:
enabled: true
ribbon:
readTimeout: 1000
connectTimeout: 1000
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 60000
logging:
level:
com.gao.consumernacosdemotimeout.client: debug
Yaml方式指定Retryer类的一个全限定路径
2.@Configuration方式
public class ProviderClientConfiguration {
@Bean
public Retryer feignRetryer() {
return new Retryer.Default();
}
}
@FeignClient(name = "provider-nacos",contextId ="provider",fallbackFactory = ProviderClientFallbackFactory.class,configuration = ProviderClientConfiguration.class)
public interface ProviderClient {
@GetMapping("test")
String test();
@GetMapping("test1")
String test1();
}
这种方式和其他@Configuration方式一样,不要在类上直接加@Configuration。
实验结果
这里可以将服务提供方接口调至读取超时阈值readTimeout。就会呈现控制台所示:
通过在响应头中指定Retry-After
除了连接超时和读取超时外,OpenFegin也会解析响应是5xx且响应头中存在`Retry-After`的值。如下是我的响应返回
@RequestMapping("test")
public ResponseEntity<String> test() throws Exception {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("Retry-After",
System.currentTimeMillis()+"");
System.err.println("hello");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.headers(responseHeaders)
.body("hello"+atomicInteger.getAndIncrement());
}