Options > appConfig > defaultConfig > OKhttp
# Options参数
@PostMapping(value = "/api/test/options")Object testOptions(Request.Options options, @RequestBody List Params);
# xx应用 appConfig
feign.client.config.xx-application.connectTimeout=2000
feign.client.config.xx-application.readTimeout=2000# feign全局默认 defaultConfig
feign.client.config.default.connectTimeout=1500
feign.client.config.default.readTimeout=3000
# OKHttp的超时配置
return new OkHttpClient.Builder().readTimeout(readTimeout, TimeUnit.MILLISECONDS).connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).writeTimeout(writeTimeout,TimeUnit.MILLISECONDS).build()
动态设置超时参数
feign 版本 >=10.3 支持
feign 版本 <=10.2.3 无法动态设置Options参数
详见SynchronousMethodHandler.invoke
@Overridepublic Object invoke(Object[] argv) throws Throwable {RequestTemplate template = buildTemplateFromArgs.create(argv);Options options = findOptions(argv);Retryer retryer = this.retryer.clone();...}Options findOptions(Object[] argv) {if (argv == null || argv.length == 0) {return this.options;}return (Options) Stream.of(argv).filter(o -> o instanceof Options).findFirst().orElse(this.options);}
// 不生效@GetMapping(value = "/tool/sleep")@Headers("k2:v2")Result sleep(@RequestParam(value = "ms") Integer ms);
测试后,不生效
核心关注下FeignClient 的 Contract
如果是 SpringMvcContract 则使用 @RequestMapping 中的 headers
如果是 Contract.Default 则使用 @Headers 注解即可
// 正解@GetMapping(value = "/tool/sleep", headers = "Retry=true")Result sleep(@RequestParam(value = "ms") Integer ms);
ps: openFeign 会默认启用SpringMvcContract
// FeignClientsConfiguration@Bean@ConditionalOnMissingBeanpublic Contract feignContract(ConversionService feignConversionService) {return new SpringMvcContract(this.parameterProcessors, feignConversionService);}
原因
详见此文
我的解法1
底层使用 OkHttpClient
定义 OkhttpInterceptor
默认针对 IOException + Get/Put 操作做重试 (可结合header做定制扩展)
上游处理 RpcException + FeignException
我的解法2
底层使用 OkHttpClient
定义 OkhttpInterceptor
实现异常的捕获、包装与转换
上游只处理 RpcException
OKHTTP默认
OkHttpClient.Builder
maxIdleConnections=5
keepAliveTime= 5 mins
feign-okhttp配置
FeignAutoConfiguration.OkHttpFeignConfiguration.httpClientConnectionPool
maxIdleConnections=200
keepAliveTime= 900 s
# 可通过属性配置 FeignHttpClientProperties
feign.httpclient.maxConnections=50
feign.httpclient.timeToLive=900
多个FeignClient 里共用一个 OkHttpClient
可以在项目启动时查看
# Feign.Builder
public Feign build() 看client
public T target(Target target) 看 target 的type和name
回收原则:idle 数量多 或 idle的时间长
(idleCount> maxIdleConnections || longestIdleDurationNs >= this.keepAliveDurationNs)
详见代码 ConnectionPool.cleanup
# ConnectionPool.cleanupif (longestIdleDurationNs >= this.keepAliveDurationNs|| idleConnectionCount > this.maxIdleConnections) {// We've found a connection to evict. Remove it from the list, then close it below (outside// of the synchronized block).connections.remove(longestIdleConnection);
}