以编程方式更改Hystrix属性

时间:2016-10-18 13:16:23

标签: java hystrix circuit-breaker

我设置了断路器,我想更改运行时的参数。需要在客户现场调整线程和超时等内容。

我像这样创建一个HystrixCommandProperties.Setter:

HystrixCommandProperties.Setter hystrixProps = 
    HystrixCommandProperties.defaultSetter()
        .withCircuitBreakerSleepWindowInMilliseconds(myconf.sleepWindow);
HystrixThreadPoolProperties.Setter threadPoolSettings = 
    HystrixThreadPoolProperties.Setter()
        .withCoreSize(myconf.threadPoolSize);

new MyCommand(HystrixCommand.Setter.withGroupKey("mygroup")
    .andCommandPropertiesDefaults(hystrixProps)
    .andThreadPoolPropertiesDefaults(threadPoolSettings));

MyCommand实现标准的HystrixCommand并调用super(hystrixProps)。

这是第一次使用,但是当我尝试在运行时更改属性(相同的组名)时没有任何反应。还有另一种以编程方式更改此方法的方法吗?

我不想浏览属性文件或指定Archaius的URL。

还有答案告诉我使用ConfigurationManager.getConfigInstance()。setProperty(“...”)来浏览Archaius。但肯定有一种类似于我创造的原始设定者的方式吗?这样做完全不同,因为这是第二次感觉很尴尬。

5 个答案:

答案 0 :(得分:6)

迟到的答案,但今天我在同样的事情上挣扎并找到了办法。

实现默认属性管理器的方式是它根据您运行的命令的名称使用HystrixCommandProperties的缓存。在第一次使用该命令时,它会缓存从传递给Command的构造函数的HystrixCommandProperties.Setter中得到的内容。

但是,使用自定义HystrixPropertiesStrategy作为Plugin,您可以覆盖缓存键(因此强制Hystrix重新评估传递给新Command实例的Setter,因为缓存键是新的,所以它认为它是一个新的命令)。

代码看起来与此类似:

public HystrixCommandFactory(....) {
    HystrixPlugins.getInstance().registerPropertiesStrategy(new HystrixPropertiesStrategyWithReloadableCache());
    updateHystrixSettings();        
}

//configurable attributes
private volatile int commandTimeoutMillis;
private volatile long lastSettingsUpdatedTimestamp;
private volatile HystrixCommand.Setter setterForNewCommands;

private void updateHystrixSettings() {
    lastSettingsUpdatedTimestamp = LocalDateTime.now().toDateTime().getMillis();
    HystrixCommandProperties.Setter propertiesSetter = HystrixCommandProperties.Setter()
        .withExecutionTimeoutInMilliseconds(commandTimeoutMillis)
        .withExecutionTimeoutEnabled(true);

    this.setterForNewCommands = HystrixCommand.Setter
        .withGroupKey(HystrixCommandGroupKey.Factory.asKey(GROUP_NAME))
        .andCommandPropertiesDefaults(propertiesSetter);

}

public void setCommandTimeoutMillis(int commandTimeoutMillis) {     
    this.commandTimeoutMillis = commandTimeoutMillis;
    updateHystrixSettings();        
}

private class HystrixPropertiesStrategyWithReloadableCache extends HystrixPropertiesStrategy {

    @Override
    public String getCommandPropertiesCacheKey(HystrixCommandKey commandKey, HystrixCommandProperties.Setter builder) {
        return String.format("%s-%d", commandKey.name(), lastSettingsUpdatedTimestamp);
    }
}

或者,你总是可以从null方法返回getCommandPropertiesCacheKey(完全关闭缓存),但是你有Hystrix每次重建HystrixCommandProperties的开销。命令称为

PS:确保使用正确的线程同步来读取和更新这些属性,因为这些属性将从不同的线程调用。为简单起见,我在此示例中省略了,但实际上我在代码中使用ReentrantReadWriteLock来保护对这些变量的访问

答案 1 :(得分:3)

供将来参考:我最终使用ConfigurationManager中的设置和字符串属性。

ConfigurationManager.getConfigInstance().setProperty("...")

它让我改变了一些东西,但是它的方式比原始代码更安全。我确实在弦乐器中输入了一段时间而斗争了,这就是为什么我要避免这种情况。

我现在将此用于我需要更改运行时的所有属性。每次更改时都会创建一个新的Hystrix断路器(新命令键)也可以作为选项,但稍后会使用属性文件中断。

答案 2 :(得分:2)

  

Hystrix属性也可以在我们的服务类里面设置   @HystrixCommand注释,为此我们使用Hystrix-Javanica   用于在我们的项目中实现注释的项目。   为此,我们需要将hystrix-javanica的依赖项添加到我们的   类路径。

对Maven的依赖:

<dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-javanica</artifactId>
    <version>x.y.z</version>
</dependency>

在@HystrixCommand注释中,我们可以使用@HystrixProperty来设置hystrix的属性。

示例@HystrixCommand属性设置:

@HystrixCommand(groupKey = "StoreSubmission", commandKey = "StoreSubmission", threadPoolKey = "StoreSubmission", commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "30000"),
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "4"),
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "60000"),
        @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "180000") }, threadPoolProperties = {
        @HystrixProperty(name = "coreSize", value = "30"),
        @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "180000") })
public String storeSubmission(ReturnType returnType, InputStream is, String id) {
}

定义这些属性的最佳方法是在外部化的 application.yaml 中,这样您就可以更好地控制它了。为不同的环境改变它们。

以下是我的application.yaml中的示例hystrix配置

hystrix:
   command.StoreSubmission.execution.isolation.thread.timeoutInMilliseconds: 30000
   command.StoreSubmission.circuitBreaker.requestVolumeThreshold: 4
   command.StoreSubmission.circuitBreaker.sleepWindowInMilliseconds: 60000
   command.StoreSubmission.metrics.rollingStats.timeInMilliseconds: 180000
   collapser.StoreSubmission.maxRequestsInBatch: 1
   collapser.StoreSubmission.requestCache.enabled: FALSE
   threadpool.StoreSubmission.coreSize: 30
   threadpool.StoreSubmission.metrics.rollingStats.timeInMilliseconds: 180000

application.yml文件的Exact格式为

hystrix:
    command:
        findAllProducts:
            execution:
                isolation:
                    thread:
                        timeoutInMilliseconds: 1000
            circuitBreaker:
                requestVolumeThreshold: 20
                errorThresholdPercentage: 50
            metrics:
                rollingStats:
                    timeInMilliseconds: 10000
                    numBuckets: 10
    threadpool:
        ProductService:
            coreSize: 10

有关Hystrix-Javanica的更多信息,请访问here

答案 3 :(得分:2)

有一种非常简单的方法可以做到这一点。它只需要两个步骤: 一个。注册正确的插件 湾使用所需的覆盖添加正确的策略。

用例:从1000毫秒覆盖ExecutionTimeoutInMilliseconds到30000毫秒

HystrixPlugins.getInstance().registerPropertiesStrategy(new HystrixPropertiesStrategy() {
            @Override
            public HystrixCommandProperties getCommandProperties(HystrixCommandKey commandKey, HystrixCommandProperties.Setter builder) {
                HystrixCommandProperties.Setter timeout
                        = HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(30000);
                return super.getCommandProperties(commandKey, timeout);
            }
        });

这里我只是覆盖了必需的属性。运行应用程序时,您可以在DEBUG模式下看到:

2018-06-08 23:18:32 [main] DEBUG c.n.h.s.p.HystrixPropertiesChainedProperty - Flipping property: hystrix.command.Client#getAllData().execution.isolation.thread.timeoutInMilliseconds to use its current value: 30000

答案 4 :(得分:0)

对于我HystrixPropertiesStrategyConfigurationManager.getConfigInstance().setProperty(..)并没有帮助,我最终创建了自己的HystrixDynamicProperty实现,如下所示,

public CustomHystrixDynamicProperty extends HystrixDynamicPropertiesArchaius {

    @Override
    public HystrixDynamicProperty<Integer> getInteger(final String name, final Integer fallback) {
         if(name.equals("Your hystrix Property")){
            return new HystrixDynamicProperty<Integer>() {
            public Integer get() {
               // Place your logic here...
              return yourValue;
             }
           public String getName(){ return name;};
           public void addCallback(Runnable callback) {};

              }
           } else {
                return super.getInteger(name,fallback);
                 }


    }
}

并在启动Spring Boot应用程序之前在“属性”下方添加。

System.setProperty("hystrix.plugin.HystrixDynamicProperties.implementation","YourPackage.CustomHystrixDynamicProperty");

对于好奇的开发人员 :: HystrixPropertiesChainedProperty中的getDynamicProperty方法通过 HystrixPropertiesStrategy 覆盖了覆盖的值,每次为“ HystrixPropertiesStrategy 设置“ HystrixCommand”之前都会被“ AbstractCommand”调用执行, 因此HystrixPropertiesStrategy的想法对我不起作用。