以编程方式更改 Hystrix 属性
Programmatically changing Hystrix properties
我设置了一个断路器,我想更改运行时的参数。线程和超时等需要在客户现场进行调整。
我这样创建 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。但是肯定必须有一种类似于我创建的原始设置器的方法吗?完全不同,因为这是第二次,感觉很尴尬。
Hystrix properties can also be set in our service class inside
@HystrixCommand annotation, for this we use the Hystrix-Javanica
project which is used for implementing the annotations in our project.
For that we need to add the dependency of hystrix-javanica into our
classpath.
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 的更多信息,请访问 here
供将来参考:我最终通过 ConfigurationManager 和字符串 属性 使用了设置。
ConfigurationManager.getConfigInstance().setProperty("...")
它让我改变了一些东西,但以一种比原始代码更不安全的方式。我确实为字符串中的拼写错误苦苦挣扎了一段时间,这就是为什么我想避免这种情况。
我现在将其用于更改运行时所需的所有属性。每次更改(新命令键)时创建一个新的 Hystrix 断路器也是一个选项,但稍后会使用属性文件中断。
迟到的答案,但今天我为同样的事情苦苦挣扎并找到了方法。
默认 属性 管理器的实现方式是根据您 运行 命令的名称使用 HystrixCommandProperties
的缓存。在第一次使用该命令时,它会缓存从 HystrixCommandProperties.Setter
传递给命令构造函数的内容,仅此而已。
但是,使用自定义 HystrixPropertiesStrategy
作为 Plugin 您可以覆盖缓存键(因此强制 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);
}
}
或者,您总是可以从 getCommandPropertiesCacheKey
方法(完全关闭缓存)中 return null
,但是这样您就有了 Hystrix 必须重建 HystrixCommandProperties
每次调用命令时
PS:确保使用适当的线程同步来读取和更新这些属性,因为这些属性将从不同的线程调用。为简单起见,我在此示例中省略了它,但实际上我在代码中使用 ReentrantReadWriteLock
来保护对这些变量的访问
有一种非常简单的方法可以做到这一点。它只需要2个步骤:
一种。注册正确的插件
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
对我来说 HystrixPropertiesStrategy
和 ConfigurationManager.getConfigInstance().setProperty(..)
没有帮助,我最终创建了自己的 HystrixDynamic属性 实现如下,
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 引导应用程序之前在下面添加 属性。
System.setProperty("hystrix.plugin.HystrixDynamicProperties.implementation","YourPackage.CustomHystrixDynamicProperty");
对于好奇的开发人员: : HystrixPropertiesChained属性 中的 getDynamic属性 方法正在通过 HystrixPropertiesStrategy[=22 覆盖覆盖的值=],每次在设置要执行的 HystrixCommand 之前都会被 "AbstractCommand" 调用,
所以 HystrixPropertiesStrategy 的想法对我不起作用。
我设置了一个断路器,我想更改运行时的参数。线程和超时等需要在客户现场进行调整。
我这样创建 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。但是肯定必须有一种类似于我创建的原始设置器的方法吗?完全不同,因为这是第二次,感觉很尴尬。
Hystrix properties can also be set in our service class inside @HystrixCommand annotation, for this we use the Hystrix-Javanica project which is used for implementing the annotations in our project. For that we need to add the dependency of hystrix-javanica into our classpath.
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 的更多信息,请访问 here
供将来参考:我最终通过 ConfigurationManager 和字符串 属性 使用了设置。
ConfigurationManager.getConfigInstance().setProperty("...")
它让我改变了一些东西,但以一种比原始代码更不安全的方式。我确实为字符串中的拼写错误苦苦挣扎了一段时间,这就是为什么我想避免这种情况。
我现在将其用于更改运行时所需的所有属性。每次更改(新命令键)时创建一个新的 Hystrix 断路器也是一个选项,但稍后会使用属性文件中断。
迟到的答案,但今天我为同样的事情苦苦挣扎并找到了方法。
默认 属性 管理器的实现方式是根据您 运行 命令的名称使用 HystrixCommandProperties
的缓存。在第一次使用该命令时,它会缓存从 HystrixCommandProperties.Setter
传递给命令构造函数的内容,仅此而已。
但是,使用自定义 HystrixPropertiesStrategy
作为 Plugin 您可以覆盖缓存键(因此强制 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);
}
}
或者,您总是可以从 getCommandPropertiesCacheKey
方法(完全关闭缓存)中 return null
,但是这样您就有了 Hystrix 必须重建 HystrixCommandProperties
每次调用命令时
PS:确保使用适当的线程同步来读取和更新这些属性,因为这些属性将从不同的线程调用。为简单起见,我在此示例中省略了它,但实际上我在代码中使用 ReentrantReadWriteLock
来保护对这些变量的访问
有一种非常简单的方法可以做到这一点。它只需要2个步骤: 一种。注册正确的插件 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
对我来说 HystrixPropertiesStrategy
和 ConfigurationManager.getConfigInstance().setProperty(..)
没有帮助,我最终创建了自己的 HystrixDynamic属性 实现如下,
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 引导应用程序之前在下面添加 属性。
System.setProperty("hystrix.plugin.HystrixDynamicProperties.implementation","YourPackage.CustomHystrixDynamicProperty");
对于好奇的开发人员: : HystrixPropertiesChained属性 中的 getDynamic属性 方法正在通过 HystrixPropertiesStrategy[=22 覆盖覆盖的值=],每次在设置要执行的 HystrixCommand 之前都会被 "AbstractCommand" 调用, 所以 HystrixPropertiesStrategy 的想法对我不起作用。