使用 Netflix Feign 和 Hystrix 设置请求超时

Setting request timeout with Netflix Feign and Hystrix

我正在使用 Feign 创建一个 REST 客户端。我的电话可以正常工作,但我想添加一些超时支持,而且我花了很多时间来弄清楚如何做到这一点。

Feign 的文档说 "to use Hystrix with Feign, add the Hystrix module to your classpath. Then use the HystrixFeign builder." 好的,现在我知道了:

service = HystrixFeign.builder()
                    .decoder(new GsonDecoder())
                    .target(ProjectService.class, URL_TO_BE_MOVED_TO_PROPS);

现在我所有的方法都返回 HystrixCommands,我可以执行或排队,但我仍然看不到如何配置它们。

Hystrix wiki (https://github.com/Netflix/Hystrix/wiki/Configuration) 说应该像这样将配置添加到 HystrixCommand 构造函数中:

public HystrixCommandInstance(int id) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
               .withExecutionTimeoutInMilliseconds(500)));
this.id = id;

但是我的命令是由 Feign built/return 执行的,所以我无法访问构造函数。

另一件值得注意的事情是 Feign-Hystrix 自述文件 (https://github.com/Netflix/feign/tree/master/hystrix) 说 "To use Hystrix with Feign, add the Hystrix module to your classpath. Then, configure Feign to use the HystrixInvocationHandler," 但是 Google 搜索 HystrixInvocationHandler 将我指向一个非 Netflix 存储库。即使我使用了它,我也看不到如何配置 Feign 来使用它。

请告诉我我很笨,这太简单了,这会让我很高兴我已经解决了这个问题,并为自己无法解决这个问题感到羞耻。

TL;DR:我想为我的 Feign 客户端发出的请求设置超时。怎么办?

事实证明,您可以使用 com.netflix.config.ConfigurationManager 的实例(来自 com.netflix.archaius:archaius-core)来设置 Hystrix 属性。

Feign 使用方法名称作为 HystrixCommandKeys,因此您可以使用这些名称访问它们的属性:

    ConfigurationManager.getConfigInstance().setProperty("hystrix.command." + methodName + ".execution.isolation.thread.timeoutInMilliseconds", 1500);

这是假设您已经使用 HystrixFeign 构建您的客户端,它将每个调用包装在 HystrixCommand 对象中。

为了简化,我创建了一个方法循环,​​这样我就可以在整个服务范围内应用超时:

private void configureHystrix() {
    Method[] methods = ProjectService.class.getMethods();

    String methodName;
    for(int i = 0; i < methods.length; i++) {
        methodName = methods[i].getName();
        ConfigurationManager.getConfigInstance().setProperty(String.format("hystrix.command.%s.execution.isolation.thread.timeoutInMilliseconds", methodName), config.getTimeoutInMillis());
    }
}

经过一些调试后,我设法将 Hystrix 超时设置如下:

HystrixFeign.builder()
   .setterFactory(getSetterFactory())
   .target(...);

// copy-paste feign.hystrix.SetterFactory.Default, just add andCommandPropertiesDefaults
private SetterFactory getSetterFactory() {
        return (target, method) ->  {
            String groupKey = target.name();
            String commandKey = Feign.configKey(target.type(), method);
            return HystrixCommand.Setter
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                    .withExecutionTimeoutInMilliseconds(15000));
        };
    }