OpenFeign提供了重试机制,重试次数针对的是客户端连接服务器的重试次数,官方文档中说:重试会对IO异常进行重试,比如:连接超时、读取超时。另外是RetryableException抛出时会重试,这个异常可以在ErrorDecoder中定义。

写在最前面

对于OpenFegin重试的触发一定是超过了Fegin或者Ribbon配置的connectTimeout和readTimeout时,才会生效。如果Hystrix配置的超时时间短了,则走的是Hystrix报的错,这样不会触发Retry

  1. feign:
  2. client:
  3. config:
  4. default:
  5. connectTimeout: 1000
  6. readTimeout: 1000
  7. loggerLevel: BASIC
  8. hystrix:
  9. enabled: true
  10. hystrix:
  11. command:
  12. default:
  13. execution:
  14. timeout:
  15. enabled: true
  16. isolation:
  17. thread:
  18. timeoutInMilliseconds: 60000
  1. feign:
  2. client:
  3. config:
  4. default:
  5. loggerLevel: BASIC
  6. hystrix:
  7. enabled: true
  8. ribbon:
  9. readTimeout: 1000
  10. connectTimeout: 1000
  11. hystrix:
  12. command:
  13. default:
  14. execution:
  15. timeout:
  16. enabled: true
  17. isolation:
  18. thread:
  19. timeoutInMilliseconds: 60000
  1. feign:
  2. client:
  3. config:
  4. default:
  5. loggerLevel: BASIC
  6. hystrix:
  7. enabled: true
  8. ribbon:
  9. readTimeout: 1000
  10. connectTimeout: 1000
  11. hystrix:
  12. command:
  13. default:
  14. execution:
  15. timeout:
  16. enabled: true
  17. isolation:
  18. thread:
  19. timeoutInMilliseconds: 100

我想传达的意思就是,hystrix配置hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds一定要长于连接和读取超时之和,才会retry配置生效

配置方式

Retryer的配置方式无外乎:Yaml@Configuration两种方式

1.Yaml方式

  1. feign:
  2. client:
  3. config:
  4. default:
  5. retryer: feign.Retryer.Default
  6. loggerLevel: BASIC
  7. hystrix:
  8. enabled: true
  9. ribbon:
  10. readTimeout: 1000
  11. connectTimeout: 1000
  12. hystrix:
  13. command:
  14. default:
  15. execution:
  16. timeout:
  17. enabled: true
  18. isolation:
  19. thread:
  20. timeoutInMilliseconds: 60000
  21. logging:
  22. level:
  23. com.gao.consumernacosdemotimeout.client: debug

Yaml方式指定Retryer类的一个全限定路径

2.@Configuration方式

  1. public class ProviderClientConfiguration {
  2. @Bean
  3. public Retryer feignRetryer() {
  4. return new Retryer.Default();
  5. }
  6. }
  7. @FeignClient(name = "provider-nacos",contextId ="provider",fallbackFactory = ProviderClientFallbackFactory.class,configuration = ProviderClientConfiguration.class)
  8. public interface ProviderClient {
  9. @GetMapping("test")
  10. String test();
  11. @GetMapping("test1")
  12. String test1();
  13. }

这种方式和其他@Configuration方式一样,不要在类上直接加@Configuration。

实验结果

这里可以将服务提供方接口调至读取超时阈值readTimeout。就会呈现控制台所示:
image.png

通过在响应头中指定Retry-After

  1. 除了连接超时和读取超时外,OpenFegin也会解析响应是5xx且响应头中存在`Retry-After`的值。如下是我的响应返回
  1. @RequestMapping("test")
  2. public ResponseEntity<String> test() throws Exception {
  3. HttpHeaders responseHeaders = new HttpHeaders();
  4. responseHeaders.set("Retry-After",
  5. System.currentTimeMillis()+"");
  6. System.err.println("hello");
  7. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
  8. .headers(responseHeaders)
  9. .body("hello"+atomicInteger.getAndIncrement());
  10. }