项目中增加依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>io.github.openfeigngroupId>
<artifactId>feign-httpclientartifactId>
<version>10.12version>
dependency>
激活配置
启动类添加载 @EnableFeignClients 如下:
@SpringBootApplication
@ComponentScans({@ComponentScan(value = "com.lydemo", excludeFilters = {@ComponentScan.Filter(IgnoreMark.class)})})
@ServletComponentScan("com.lydemo.helloworld.filter")
@EnableFeignClients
public class BootApplication {
基础配置 包括 超时,httpclient,日志配置
# feign配置
feign.httpclient.max-connections=200
feign.httpclient.max-connections-per-route=50
feign.httpclient.connection-timeout=1500
feign.client.config.default.connect-timeout=1500
feign.client.config.default.read-timeout=5000
feign.client.config.default.loggerLevel=BASIC
总结:
配置解析:
通过 org.springframework.cloud.openfeign.FeignClient#configuration 字段注释 发现 默认配置 在 org.springframework.cloud.openfeign.FeignClientsConfiguration
// org.springframework.cloud.openfeign.FeignClientsConfiguration#feignRetryer
@Bean
@ConditionalOnMissingBean
public Retryer feignRetryer() {
return Retryer.NEVER_RETRY;
}
参考:
说明
启用配置
增加如下依赖:
org.springframework.retry
spring-retry
添加如下 配置
# loadbalancer 配置
# loadbalancer 配置 (retry.enabled 也会控制 RetryableFeignBlockingLoadBalancerClient 的生成)
spring.cloud.loadbalancer.retry.enabled=true
spring.cloud.loadbalancer.retry.max-retries-on-same-service-instance=0
spring.cloud.loadbalancer.retry.max-retries-on-next-service-instance=1
重试测试
logback 添加如下配置
启动 两个被调用实例 (我启动了helo2 demo 微服务),然后 快速停止其中一个,快速点击调用方实例,出现如下日志:
重试 日志如下
remote.feign.Helo2Client - [log,72] - [Helo2Client#queryUserByName] ---> GET http://HELO2/helo2/queryUserByName?name=lala&sign=2e3817293fc275dbee74bd71ce6eb056 HTTP/1.1
2021-07-25 01:54:29.508 [http-nio-46092-exec-7] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,120] - Service instance retrieved from LoadBalancedRetryContext: was null. Reattempting service instance selection
2021-07-25 01:54:29.510 [http-nio-46092-exec-7] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,128] - Selected service instance: [EurekaServiceInstance@6b1e9f0 instance = InstanceInfo [instanceId = helo2:192.168.3.6:42379, appName = HELO2, hostName = 192.168.3.6, status = UP, ipAddr = 192.168.3.6, port = 42379, securePort = 443, dataCenterInfo = com.netflix.appinfo.MyDataCenterInfo@2fff1f76]
2021-07-25 01:54:29.510 [http-nio-46092-exec-7] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,146] - Using service instance from LoadBalancedRetryContext: [EurekaServiceInstance@6b1e9f0 instance = InstanceInfo [instanceId = helo2:192.168.3.6:42379, appName = HELO2, hostName = 192.168.3.6, status = UP, ipAddr = 192.168.3.6, port = 42379, securePort = 443, dataCenterInfo = com.netflix.appinfo.MyDataCenterInfo@2fff1f76]
2021-07-25 01:54:29.514 [http-nio-46092-exec-7] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,120] - Service instance retrieved from LoadBalancedRetryContext: was null. Reattempting service instance selection
2021-07-25 01:54:29.523 [http-nio-46092-exec-7] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,128] - Selected service instance: [EurekaServiceInstance@6996f084 instance = InstanceInfo [instanceId = helo2:192.168.3.6:8080, appName = HELO2, hostName = 192.168.3.6, status = UP, ipAddr = 192.168.3.6, port = 8080, securePort = 443, dataCenterInfo = com.netflix.appinfo.MyDataCenterInfo@781923c7]
2021-07-25 01:54:29.523 [http-nio-46092-exec-7] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,146] - Using service instance from LoadBalancedRetryContext: [EurekaServiceInstance@6996f084 instance = InstanceInfo [instanceId = helo2:192.168.3.6:8080, appName = HELO2, hostName = 192.168.3.6, status = UP, ipAddr = 192.168.3.6, port = 8080, securePort = 443, dataCenterInfo = com.netflix.appinfo.MyDataCenterInfo@781923c7]
2021-07-25 01:54:29.533 [http-nio-46092-exec-7] DEBUG com.lydemo.helloworld.remote.feign.Helo2Client - [log,72] - [Helo2Client#queryUserByName] <--- HTTP/1.1 200 (25ms)
正常没有重试日志如下:
2021-07-25 02:10:55.381 [http-nio-46092-exec-10] DEBUG com.lydemo.helloworld.remote.feign.Helo2Client - [log,72] - [Helo2Client#queryUserByName] ---> GET http://HELO2/helo2/queryUserByName?name=lala&sign=2e3817293fc275dbee74bd71ce6eb056 HTTP/1.1
2021-07-25 02:10:55.381 [http-nio-46092-exec-10] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,120] - Service instance retrieved from LoadBalancedRetryContext: was null. Reattempting service instance selection
2021-07-25 02:10:55.382 [http-nio-46092-exec-10] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,128] - Selected service instance: [EurekaServiceInstance@4a2d6add instance = InstanceInfo [instanceId = helo2:192.168.3.6:8080, appName = HELO2, hostName = 192.168.3.6, status = UP, ipAddr = 192.168.3.6, port = 8080, securePort = 443, dataCenterInfo = com.netflix.appinfo.MyDataCenterInfo@781923c7]
2021-07-25 02:10:55.382 [http-nio-46092-exec-10] DEBUG org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient - [lambda$execute$2,146] - Using service instance from LoadBalancedRetryContext: [EurekaServiceInstance@4a2d6add instance = InstanceInfo [instanceId = helo2:192.168.3.6:8080, appName = HELO2, hostName = 192.168.3.6, status = UP, ipAddr = 192.168.3.6, port = 8080, securePort = 443, dataCenterInfo = com.netflix.appinfo.MyDataCenterInfo@781923c7]
2021-07-25 02:10:55.387 [http-nio-46092-exec-10] DEBUG com.lydemo.helloworld.remote.feign.Helo2Client - [log,72] - [Helo2Client#queryUserByName] <--- HTTP/1.1 200 (5ms)
说明
使用配置
添加如下依赖
org.springframework.cloud
spring-cloud-starter-circuitbreaker-resilience4j
配置
feign.circuitbreaker.enabled=true
因为添加了 resilience4j-spring-boot2 所以 resilience4j 可以如下配置:
# resilience4j circuitbreaker 配置
resilience4j.circuitbreaker:
configs:
default:
slidingWindowType: COUNT_BASED
slidingWindowSize: 100
minimumNumberOfCalls: 100
permittedNumberOfCallsInHalfOpenState: 10
automaticTransitionFromOpenToHalfOpenEnabled: true
waitIntervalFunctionInOpenState: 60
failureRateThreshold: 50
eventConsumerBufferSize: 10
# recordExceptions:
# - org.springframework.web.client.HttpServerErrorException
# - java.io.IOException
# ignoreExceptions:
# - java.lang.IllegalStateException
instances:
testService:
baseConfig: default
slidingWindowSize: 10
minimumNumberOfCalls: 2
failureRateThreshold: 1
recordExceptions:
- java.lang.Throwable
属性配置优先级高于Java Customizer configuration.
参考:
https://docs.spring.io/spring-cloud-circuitbreaker/docs/current/reference/html/#usage-documentation
。