configuration - 你如何覆盖 OpenFeign 的 Hystrix 配置?
问题描述
你如何覆盖 OpenFeign 的 Hystrix 默认配置?大多数文档都是针对 SpringBoot + OpenFeign 的,它有自己的 Spring 特定的配置覆盖系统。
理想情况下,可以为客户端配置 Hystrix 核心大小,并基于每个端点配置和超时。
解决方案
Hystrix OpenFeignsetterFactory()
在构建器上有一个方法,允许您传入一个 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))
上面的示例使用OpenFeign 文档中的样板来根据目标端点函数正确命名 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
中。
推荐阅读
- java - 通过一个 spring-rabbit 服务中的一个消费者同时处理多个 amqp 消息
- android - Android 应用程序区域设置语言更改不适用于 EN,但适用于其他语言
- swift - 自定义披露视图 NSOutlineView Swift
- html - 是否可以在事务运行期间禁用表单的所有 HTML 元素
- javascript - Vue.js 和电影数据库 API 返回错误 403
- ios - 在 xcode11 中构建一个带有完整位码的胖框架
- python - 用 for 循环计算热力学性质
- c++ - GTKMM 在一个简单的应用程序中泄漏内存
- unix - 将文件复制或移动到目录中,并从另一个进程进行并行处理
- javascript - 我不知道如何在 svelte.js 中使用生命周期