OpenFeign提供了重试机制,重试次数针对的是客户端连接服务器的重试次数,官方文档中说:重试会对IO异常进行重试,比如:连接超时、读取超时。另外是RetryableException抛出时会重试,这个异常可以在ErrorDecoder中定义。
写在最前面
对于OpenFegin重试的触发一定是超过了Fegin或者Ribbon配置的connectTimeout和readTimeout时,才会生效。如果Hystrix配置的超时时间短了,则走的是Hystrix报的错,这样不会触发Retry
feign:client:config:default:connectTimeout: 1000readTimeout: 1000loggerLevel: BASIChystrix:enabled: truehystrix:command:default:execution:timeout:enabled: trueisolation:thread:timeoutInMilliseconds: 60000
feign:client:config:default:loggerLevel: BASIChystrix:enabled: trueribbon:readTimeout: 1000connectTimeout: 1000hystrix:command:default:execution:timeout:enabled: trueisolation:thread:timeoutInMilliseconds: 60000
feign:client:config:default:loggerLevel: BASIChystrix:enabled: trueribbon:readTimeout: 1000connectTimeout: 1000hystrix:command:default:execution:timeout:enabled: trueisolation:thread:timeoutInMilliseconds: 100
我想传达的意思就是,hystrix配置
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds一定要长于连接和读取超时之和,才会retry配置生效
配置方式
Retryer的配置方式无外乎:Yaml和@Configuration两种方式
1.Yaml方式
feign:client:config:default:retryer: feign.Retryer.DefaultloggerLevel: BASIChystrix:enabled: trueribbon:readTimeout: 1000connectTimeout: 1000hystrix:command:default:execution:timeout:enabled: trueisolation:thread:timeoutInMilliseconds: 60000logging:level:com.gao.consumernacosdemotimeout.client: debug
Yaml方式指定Retryer类的一个全限定路径
2.@Configuration方式
public class ProviderClientConfiguration {@Beanpublic 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());}
