実行時のパラメータを変更したいサーキットブレーカを設定しています。スレッドやタイムアウトなどは、お客様のサイトで調整する必要があります。
次のような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を実行するように指示する回答もあります。しかし、確かに私が作成した元のセッターに似た方法がなければなりませんか? 2回目なので、まったく違うことをするのは気まずいです。
将来の参考のために:ConfigurationManagerと文字列プロパティを介して設定を使用することになりました。
ConfigurationManager.getConfigInstance().setProperty("...")
それは私に物事を変えさせてくれますが、元のコードよりもタイプセーフではありません。ストリングのタイプミスでしばらく苦労しました。それが私がそれを避けたい理由です。
現在、ランタイムを変更する必要があるすべてのプロパティにこれを使用しています。何かが変更されるたびに新しいHystrixサーキットブレーカー(新しいコマンドキー)を作成することもオプションですが、後でプロパティファイルを使用すると壊れます。
遅い答えですが、今日私は同じことに苦労し、方法を見つけました。
デフォルトのプロパティマネージャーを実装する方法は、実行するコマンドの名前に基づいてHystrixCommandProperties
のキャッシュを使用することです。コマンドの最初の使用時に、コマンドのコンストラクターに渡されたHystrixCommandProperties.Setter
から取得したものをキャッシュします。それだけです。
ただし、カスタムHystrixPropertiesStrategy
を プラグイン として使用すると、キャッシュキーをオーバーライドできます(したがって、キャッシュキーは次のようになるため、Hystrixに新しいコマンドインスタンスに渡されたセッターを再評価させます。新しいので、それは新しいコマンドだと思います)。
その場合、コードは次のようになります。
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
を使用して、これらの変数へのアクセスを保護しています
これを行うには非常に簡単な方法があります。 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
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の詳細については、 ここ をご覧ください。
HystrixPropertiesStrategyもPolledConfigurationSourceも機能しなかった3時間後に、私はついに解決策を見つけました。
これが私のために働いたものです
HystrixThreadPoolMetrics.getInstance(HystrixThreadPoolKey.Factory.asKey("HelloWorldPool")).getThreadPool().setCorePoolSize(threadCount);
それでも、それが正しい解決策であるかどうかを確認する必要があります。
私にとって、HystrixPropertiesStrategy
とConfigurationManager.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のアイデアは私にはうまくいきませんでした。