你如何覆盖 OpenFeign 的 Hystrix 配置?
Posted
技术标签:
【中文标题】你如何覆盖 OpenFeign 的 Hystrix 配置?【英文标题】:How do you override the Hystrix configuration for OpenFeign? 【发布时间】:2021-11-10 22:07:42 【问题描述】:如何覆盖 OpenFeign 的 Hystrix 默认配置?大部分文档都是针对 SpringBoot + OpenFeign 的,它有自己的 Spring 特定配置覆盖系统。
理想情况下,可以为客户端配置 Hystrix 核心大小,并基于每个端点配置和超时。
【问题讨论】:
【参考方案1】:Hystrix OpenFeign 在构建器上有一个 setterFactory()
方法,允许您传入一个 SetterFactory lambda 函数,该函数在设置每个目标端点时执行:
final SetterFactory hystrixConfigurationFactory = (target, method) ->
final String groupKey = target.name();
final String commandKey = method.getAnnotation(RequestLine.class).value();
// Configure default thread pool properties
final HystrixThreadPoolProperties.Setter hystrixThreadPoolProperties = HystrixThreadPoolProperties.Setter()
.withCoreSize(50)
.withMaximumSize(200)
.withAllowMaximumSizeToDivergeFromCoreSize(true);
return HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
.andThreadPoolPropertiesDefaults(hystrixThreadPoolProperties);;
;
final MyTargetClient myTargetClient = HystrixFeign.builder()
.setterFactory(hystrixConfigurationFactory)
.client(new OkHttpClient())
.encoder(new JacksonEncoder(objectMapper))
.decoder(new JacksonDecoder(objectMapper))
.target(new Target.HardCodedTarget<>(MyTargetClient.class, "customclientname", baseUrl))
上面的例子使用boilerplate from the OpenFeign documentation根据目标端点函数正确命名Hystrix键。然后,它还将默认线程池属性核心大小和最大核心大小配置为所有目标函数的默认值。
然而,由于这个工厂是为每个目标端点调用的,我们实际上可以在每个端点的基础上覆盖 Hystrix 配置。 Hystrix 超时是一个很好的用例:有时有些端点比其他端点花费的时间更长,我们需要考虑到这一点。
最简单的方法是首先创建一个注释并将其放置在需要覆盖的目标端点上:
/**
* Override Hystrix configuration for Feign targets.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface HystrixOverride
int DEFAULT_EXECUTION_TIMEOUT = 2_000;
/**
* Execution timeout in milliseconds.
*/
int executionTimeout() default DEFAULT_EXECUTION_TIMEOUT;
interface MyTargetClient
@HystrixOverride(executionTimeout = 10_000)
@RequestLine("GET /rest/storeCode/V1/products")
Products searchProducts(@Param("storeCode") String storeCode, @QueryMap Map<String, Object> queryMap);
@RequestLine("GET /rest/storeCode/V1/products/sku")
Product getProduct(@Param("storeCode") String storeCode, @Param("sku") String sku);
在上面的示例中,搜索 API 可能需要更长的时间才能加载,因此我们对此进行了覆盖。
仅仅将覆盖注释放在目标端点函数上是不够的。我们需要回到我们的工厂并更新它以使用注释中的数据:
final SetterFactory hystrixConfigurationFactory = (target, method) ->
final String groupKey = target.name();
final String commandKey = method.getAnnotation(RequestLine.class).value();
// Configure per-function Hystrix configuration by referencing annotations
final HystrixCommandProperties.Setter hystrixCommandProperties = HystrixCommandProperties.Setter();
final HystrixOverride hystrixOverride = method.getAnnotation(HystrixOverride.class);
final int executionTimeout = (hystrixOverride == null)
? HystrixOverride.DEFAULT_EXECUTION_TIMEOUT
: hystrixOverride.executionTimeout();
hystrixCommandProperties.withExecutionTimeoutInMilliseconds(executionTimeout);
// Configure default thread pool properties
final HystrixThreadPoolProperties.Setter hystrixThreadPoolProperties = HystrixThreadPoolProperties.Setter()
.withCoreSize(50)
.withMaximumSize(200)
.withAllowMaximumSizeToDivergeFromCoreSize(true);
return HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
.andCommandPropertiesDefaults(hystrixCommandProperties)
.andThreadPoolPropertiesDefaults(hystrixThreadPoolProperties);;
;
上面检查是否存在覆盖注释,然后使用该注释中的数据来配置该目标端点的执行超时。如果不存在覆盖,则将使用 HystrixOverride 端点的默认值。然后将生成的 hystrixCommandProperties
变量插入到最后的整体 HystrixCommand.Setter
中。
【讨论】:
以上是关于你如何覆盖 OpenFeign 的 Hystrix 配置?的主要内容,如果未能解决你的问题,请参考以下文章
OpenFeign + Hystrix - 不同客户端的不同超时
springcloud中openfeign止hystrix的几个问题
springcloud中openfeign止hystrix的几个问题