参考記事
SpringCloud(6)-ヒューズのダウングレードの理解、Hystrixの実際の戦闘
Spring CloudHystrixサービスのフォールトトレランス
Spring CloudHystrixダッシュボードダッシュボード
HystrixヒューズVSダウングレード
ヒューズの劣化は、アバランシェ効果に対処するためのマイクロサービスリンク保護メカニズムです。ファンアウトリンクのマイクロサービスが利用できない場合、または応答時間が長すぎる場合、サービスが劣化し、ノードのマイクロサービス呼び出しは次のようになります。ヒューズ、そしてエラーの対応する情報をすばやく返します。
類似点:
同じ目標は、システムのクラッシュを防ぐために、可用性と信頼性から始めることです。
ユーザーエクスペリエンスは似ています。最終的にユーザーエクスペリエンスを向上させるのは、一部の機能が一時的に利用できなくなることです。
違い:
ダウングレード:ダウンストリームサービスにアクセスするときに、タイムアウト、障害時間、障害、または現在の制限がある場合は、Hystrixで指定された方法にアクセスし、バックアップ情報にすばやく戻って、ダウングレード操作を実行します。
ヒューズ:ダウンストリームサービスへのアクセス時にエラーが多すぎる場合、しきい値を超えています。その後、サービスコールは直接融合され、スタンバイ情報は次回サービスを呼び出さずに直接返されます。両方の融合は、適格なダウングレードです。
Hystrixは、ヒューズを構成するために次の主要なパラメーターを提供します。
circuitBreaker.requestVolumeThreshold //滑动窗口的大小,默认为20
circuitBreaker.sleepWindowInMilliseconds //过多长时间,熔断器再次检测是否开启,默认为5000,即5s钟
circuitBreaker.errorThresholdPercentage //错误率,默认50%
3つのパラメーターをまとめると、表現される意味は次のとおりです。
20個のリクエストの50%が失敗すると、ヒューズが開きます。この時点でサービスが再度呼び出されると、失敗は直接返され、リモートサービスは呼び出されません。5秒後まで、トリガー条件を再確認して、ヒューズを閉じるか、開き続けるかを決定します。
Hystrixインスタンス
1.jarをインポートします
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2. @ EnableCircuitBreakerをエントリクラスに追加します
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class DemoApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@EnableHystrixを追加することもできます。@EnableHystrixと@EnableCircuitBreakerは同等です。
3、 @ HystrixCommand
@HystrixCommand(fallbackMethod = "getUserDefault")
public User getUser(@PathVariable Long id) {
return restTemplate.getForObject("http://Server-Provider/user/{id}", User.class, id);
}
public User getUserDefault(Long id) {
User user = new User();
user.setId(-1L);
user.setUsername("defaultUser");
user.setPassword("123456");
return user;
}
@HystrixCommandアノテーションをgetUserメソッドに追加しました。アノテーションのfallbackMethod属性は、呼び出されたメソッドが使用できない場合のコールバックメソッド(サービスが壊れたときのコールバック処理ロジック、つまりサービスの低下)を指定します。これがgetUserDefaultメソッドです( getUserメソッドを使用する必要がありますパラメーターと戻り値のタイプは同じです)。
Hystrixの一般的な注意事項
HystrixCommand
属性 | 説明 | サンプル |
---|---|---|
fallbackMethod | 呼び出されたメソッドが使用できない場合のコールバックメソッドを指定します | fallbackMethod =“ getUserDefault” |
ignoreExceptions | 例外がサービスの低下を引き起こさないことを指定します | ignoreExceptions = {NullPointerException.class} |
commandKey | コマンドの名前 | commandKey =“ getUserById” |
groupKey | グループ名 | groupKey =“ userGroup” |
threadPoolKey | スレッドプール名 | threadPoolKey =“ getUserThread” |
メソッドによってスローされる例外情報については、サービス劣化メソッドでThrowableオブジェクトを使用して取得できます。
@HystrixCommand(fallbackMethod = "getUserDefault",commandKey = "getUserById", groupKey = "userGroup",
threadPoolKey = "getUserThread" , ignoreExceptions = {
NullPointerException.class})
public User getUser(@PathVariable Long id) {
//代码省略
}
public User getUserDefault(Long id, Throwable e) {
//代码省略
}
上記の構成では、コマンドの名前をgetUserById、グループ名をuserGroup、スレッドプール名をgetUserThreadとして指定しています。
コマンドグループを設定することにより、Hystrixはコマンドアラーム、ダッシュボード、およびその他の情報をグループに従って整理およびカウントします。デフォルトでは、Hystrixコマンドはスレッドプールをグループ名で分割します。つまり、同じグループ名のコマンドは同じスレッドプールに配置されます。スレッドプール名がthreadPoolKeyで設定されている場合は、スレッドプール名に従って分割されます。 。
getUserメソッドが呼び出されると、ログは次のように出力されます。
2018-06-06 15:32:55.945 INFO 16192 --- [getUserThread-1] com.example.demo.Service.UserService : 获取用户信息
スレッド名がgetUserThread-1であることがわかります。
Hystrixキャッシュ
1.フィルターを追加します。
実際、Hystrixのキャッシュはまだまったく味がなく、リクエストキャッシュは一度書き込まれるだけでなく、結果は変更されませんが、リクエストがコントローラーに到着するたびに、HystrixRequestContextを初期化する必要がありますが、前のキャッシュはそうではありません。同じリクエストで同じ結果が保証されます。同じリクエストで最初にアクセスした後、結果がキャッシュされます。キャッシュのライフサイクルは1つのリクエストのみです。
@Component
@WebFilter(filterName = "hystrixRequestContextServletFilter", urlPatterns = "/*", asyncSupported = true)
public class HystrixRequestContextServletFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HystrixRequestContext context = HystrixRequestContext.initializeContext();
filterChain.doFilter(servletRequest, servletResponse);
context.close();
}
@Override
public void destroy() {
}
}
2. @CacheResultを追加し、キーを指定して、次の方法でキーを指定します。
a。@ CacheKeyアノテーションを使用してキーを指定します
@CacheResult
@HystrixCommand(fallbackMethod = "getUserDefault", commandKey = "getUserById", groupKey = "userGroup",
threadPoolKey = "getUserThread")
public User getUser(@CacheKey("id") @PathVariable Long id) {
log.info("获取用户信息");
return restTemplate.getForObject("http://Server-Provider/user/{id}", User.class, id);
}
b。メソッドで指定します。メソッドの戻り値は、String型である必要があります。
public String getCacheKey(Long id) {
return String.valueOf(id);
}
@CacheResult(cacheKeyMethod = "getCacheKey")
@HystrixCommand(fallbackMethod = "getUserDefault", commandKey = "getUserById", groupKey = "userGroup",
threadPoolKey = "getUserThread")
public User getUser(Long id) {
log.info("获取用户信息");
return restTemplate.getForObject("http://Server-Provider/user/{id}", User.class, id);
}
3. @ CacheRemoveキャッシュの削除。対応するキャッシュを時間内にクリアする必要があります。そうしないと、キャッシュされたデータと実際のデータの間に不整合が発生します。
@CacheRemove(commandKey = "getUserById")
@HystrixCommand
public void updateUser(@CacheKey("id") User user) {
this.restTemplate.put("http://Server-Provider/user", user);
}
@CacheRemoveのcommandKey属性は、getUserで定義されている属性と一致しています。
HystrixCollapserリクエストのマージ
リクエストのマージとは、複数の単一のリクエストを1つのリクエストにマージしてサービスプロバイダーを呼び出すことです。これにより、サービスプロバイダーの負荷が軽減され、高い同時実行性が実現します。まれに使用されます。確認したい場合は、Spring CloudHystrixサービスのフォールトトレランスをクリックしてください。
Hystrix属性
構成方法:
Execution.isolation.strategy:この属性は、実行分離戦略を設定するために使用されます。次の2つのオプションがあり、デフォルト値はTHREADです。
- THREAD:スレッドプールを介した分離の戦略。これは別のスレッドで実行され、同時実行の制限はスレッドプール内のスレッドの数によって制限されます。
- SEMAPHORE:セマフォによる隔離の戦略。呼び出し元のスレッドで実行され、同時実行の制限はセマフォの数によって制限されます。
1.グローバル構成:application.properties
hystrix.command.default.execution.isolation.strategy = "THREAD"
2.構成例:application.properties
hystrix.command.{HystrixCommandKey}.execution.isolation.strategy = "THREAD"
HystrixCommandKeyは、@ HystrixCommandのcommandKey値です。
3.インスタンス構成:@HystrixProperty
@HystrixCommand(fallbackMethod = "getUserDefault",
commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value"THREAD")})
public User getUser(Long id) {
log.info("获取用户信息");
return restTemplate.getForObject("http://Server-Provider/user/{id}", User.class, id);
}
属性リスト
実行実行構成
Execution.isolation.strategy:この属性は、実行分離戦略を設定するために使用されます。次の2つのオプションがあります。デフォルト値:THREAD
- THREAD:スレッドプールを介した分離の戦略。これは別のスレッドで実行され、同時実行の制限はスレッドプール内のスレッドの数によって制限されます。
- SEMAPHORE:セマフォによる隔離の戦略。呼び出し元のスレッドで実行され、同時実行の制限はセマフォの数によって制限されます。
Execution.isolation.thread.timeoutinMilliseconds:このプロパティは、HystrixCommand実行のタイムアウト期間をミリ秒単位で構成するために使用されます。HystrixCommandの実行時間が構成値を超えると、Hystrixは実行コマンドをTIMEOUTとしてマークし、サービス低下処理ロジックに入ります。デフォルト値:1000ミリ秒
execute.timeout.enabled:このプロパティは、タイムアウト期間を有効にするかどうかをHystrixCommandの実行を構成するために使用されます。デフォルトはtrueです。falseに設定されている場合、execution.isolation.thread.timeoutinMillisecondsプロパティの構成は機能しなくなります。
coreSize:このパラメーターは、コマンドスレッドプール内のコアスレッドの数を設定するために使用されます。この値は、コマンドの同時実行の最大数です。デフォルト:10
execute.isolation.semaphore.maxConcurrentRequests:HystrixCommand分離戦略がセマフォを使用する場合、このプロパティは、セマフォのサイズ(同時要求の数)を構成するために使用されます。同時リクエストの最大数が設定値に達すると、それ以降のリクエストは拒否されます。デフォルト:10
fallback.enabled:この属性は、サービス低下ポリシーを有効にするかどうかを設定するために使用されます。falseに設定されている場合、要求が失敗するか拒否が発生すると、ダウングレードされたサービスは呼び出されません。デフォルト:true
サーキットブレーカーヒューズ構成
CircuitBreaker.enabled:この属性は、サービス要求コマンドが失敗したときに、回路ブレーカーを使用してヘルスインジケーターと回路ブレーカー要求を追跡するかどうかを決定するために使用されます。デフォルト:true
CircuitBreaker.requestVolumeThreshold:このプロパティは、ローリングタイムウィンドウでのサーキットブレーカーの融合要求の最小数を設定するために使用されます。たとえば、デフォルト値が20の場合、ローリングタイムウィンドウ(デフォルトでは10秒)内に19の要求のみが受信されると、19の要求すべてが失敗しても、回路ブレーカーは開きません。デフォルト:20
CircuitBreaker.errorThresholdPercentage:このプロパティは、回路ブレーカーを開くためのエラーパーセンテージ条件を設定するために使用されます。たとえば、デフォルト値が5000の場合、ローリングタイムウィンドウで、リクエスト数がcircuitBreaker.requestVolumeThresholdの値を超えると、エラーリクエスト数のパーセンテージが50を超えると、サーキットブレーカーが次のように設定されます。 「オープン」状態。それ以外の場合は、「オフ」状態に設定されます。デフォルト:50
CircuitBreaker.sleepWindowinMilliseconds:このプロパティは、回路ブレーカーが開いた後のスリープ時間ウィンドウを設定するために使用されます。スリープ時間ウィンドウが終了すると、サーキットブレーカは「ハーフオープン」状態に設定され、溶断の要求コマンドが試行されます。それでも失敗する場合、サーキットブレーカは引き続き「オープン」に設定されます。状態であり、成功した場合は「クローズ」状態に設定されます。デフォルト:5000
CircuitBreaker.forceOpen:このプロパティがtrueに設定されている場合、回路ブレーカーは強制的に「オープン」状態になり、すべての要求を拒否します。この属性は、circuitBreaker.forceClosed属性よりも優先されます。
CircuitBreaker.forceClosed:このプロパティがtrueに設定されている場合、回路ブレーカーは強制的に「閉じた」状態になり、すべての要求を受信します。CircuitBreaker.forceOpenプロパティがtrueの場合、このプロパティは有効になりません。デフォルト:false
requestContext
requestCache.enabled:このプロパティは、リクエストのキャッシュを有効にするかどうかを構成するために使用されます。
その他の属性については、Spring CloudHystrixサービスのフォールトトレランスを参照してください。
Hystrixの原理
Hystrix処理フロー
リソースの分離
リソースの分離とは、主にスレッドの分離を指します。Hystrixは、スレッドプールとセマフォの2つのスレッド分離方法を提供します。
スレッド分離-スレッドプール
Hystrixは、コマンドモードを使用して、要求を送信するオブジェクトと要求を実行するオブジェクトを分離し、さまざまなタイプのビジネス要求を対応するコマンド要求にカプセル化します。
たとえば、order service query product、query product request-> product command; product service query Inventory、query Inventory request-> inventoryコマンド。また、コマンドの種類ごとにスレッドプールを構成します。コマンドを初めて作成するときに、構成に従ってスレッドプールが作成され、CommodityCommandなどのConcurrentHashMapに配置されます。
final static ConcurrentHashMap<String, HystrixThreadPool> threadPools = new ConcurrentHashMap<String, HystrixThreadPool>();
...
if (!threadPools.containsKey(key)) {
threadPools.put(key, new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder));
}
後続の製品クエリ要求に対してコマンドが作成されると、作成されたスレッドプールが再利用されます。
スレッドの分離-セマフォ
セマフォを設定して、特定の依存関係への同時呼び出しの数を制限します。
スレッドプールを使用する場合、リクエストを送信するスレッドと依存サービスを実行するスレッドは同じではありません。セマフォを使用する場合、リクエストを送信するスレッドと依存サービスを実行するスレッドは同じであり、両方とも同じです。リクエストを開始するスレッドです。
スレッド分離の概要
スレッドの切り替え | 非同期をサポート | サポートタイムアウト | サポートヒューズ | 制限 | オーバーヘッド |
---|---|---|---|---|---|
信号 | 番号 | 番号 | 番号 | はい | はい |
スレッドプール | はい | はい | はい | はい | はい |
通常の状況では、スレッドプールによって導入されるオーバーヘッドは十分に小さいため、コストやパフォーマンスに大きな影響はありません。ただし、メモリキャッシュのみに依存するなど、アクセスレイテンシが非常に低い一部のサービスでは、スレッドプールによって生じるオーバーヘッドがより明白になります。現時点では、スレッドプール分離テクノロジは適切ではありません。より軽量な方法を検討する必要があります。 、信号など。ボリュームの分離。
スレッドプールとセマフォの両方が、回路の遮断と電流制限をサポートします。スレッドプールと比較して、セマフォはスレッドの切り替えを必要としないため、不要なオーバーヘッドを回避できます。ただし、セマフォは非同期をサポートせず、タイムアウトもサポートしません。つまり、要求されたサービスが利用できない場合、セマフォは制限を超える要求を制御してすぐに戻りますが、セマフォを既に保持しているスレッドは待機することしかできません。サービス応答またはタイムアウトリターンから、つまり、長い待機が発生する可能性があります。スレッドプールモードでは、応答しないサービスが指定された時間を超えると、Hystrixはスレッドにすぐに終了し、割り込みに応答して戻るように通知します。
ヒューズワークフロー
ヒューズの詳細なプロセスは次のとおりです。
最初のステップは、allowRequest()を呼び出して、要求をスレッドプールに送信できるかどうかを判断することです。
- ヒューズが強制的に開かれた場合、circuitBreaker.forceOpenはtrueであり、解放は許可されず、戻ります。
- ヒューズが強制的に閉じられている場合、circuitBreaker.forceClosedはtrueであり、解放できます。さらに、ヒューズの実際のステータスに注意を払う必要はありません。つまり、ヒューズは統計とスイッチステータスを維持しますが、有効にはなりません。
2番目のステップは、isOpen()を呼び出して、ヒューズスイッチが開いているかどうかを確認することです。ヒューズスイッチが開いている場合は、3番目のステップに進み、そうでない場合は続行します。
- サイクル内のリクエストの総数がcircuitBreaker.requestVolumeThresholdの値よりも少ない場合、リクエストは通過できます。それ以外の場合は続行されます。
- ある期間のエラー率がcircuitBreaker.errorThresholdPercentageの値よりも小さい場合、要求は通過できます。それ以外の場合は、ヒューズスイッチを開き、3番目の手順に入ります。
3番目のステップは、allowSingleTest()を呼び出して、単一の要求の通過が許可されているかどうかを判別し、依存サービスが復元されているかどうかを確認することです。
- ヒューズが開いていて、ヒューズが開いてからの時間、または最後の試行要求の解放時間がcircuitBreaker.sleepWindowInMillisecondsの値を超えると、ヒューズは半開状態になり、試行要求を解放できます。解放することは許可されていません。