12

我设置了一个断路器,我想更改运行时的参数。线程和超时之类的东西需要在客户现场进行调整。

我像这样创建一个 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。但肯定有一种类似于我创建的原始设置器的方法吗?这样做完全不同,因为这是第二次,感觉很尴尬。

4

5 回答 5

10

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

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

但是,使用自定义HystrixPropertiesStrategy作为插件,您可以覆盖缓存键(并因此强制 Hystrix 重新评估传递给新命令实例的 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每次调用 Command 时重新构建

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

于 2017-05-22T19:47:59.573 回答
7

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

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

它让我改变了一些事情,但以一种比原始代码更不安全的方式。我确实为字符串中的错字挣扎了一段时间,这就是为什么我想避免这种情况。

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

于 2016-11-15T09:04:14.177 回答
4

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

用例:将 ExecutionTimeoutInMilliseconds 从 1000 毫秒改写为 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
于 2018-06-08T22:35:05.303 回答
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 文件的确切格式是

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 的更多信息,请访问此处

于 2016-11-01T09:40:13.697 回答
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覆盖覆盖的值,每次在设置 HystrixCommand 执行之前,“AbstractCommand”都会调用它,所以 HystrixPropertiesStrategy 的想法对我不起作用。

于 2019-12-08T22:30:52.740 回答