Hystrix HystricCommand配置参数全解析

https://www.cnblogs.com/zhenbianshu/p/9630167.html

https://juejin.im/post/5c4f18cb6fb9a049ff4e8524

https://blog.csdn.net/tongtong_use/article/details/78611225

前言


不久前在部门周会上分享了 Hystrix 源码解析之后,就无奈地背上了专家包袱,同事们都认为我对 Hystrix 很熟,我们接触 Hystrix 更多的还是工作中的使用和配置,所以很多人一遇到 Hystrix 的配置问题就会过来问我。为了不让他们失望,我把 Hystrix 的 配置文档 仔细看了一遍,将有疑问的点通过翻源码、查官方 issue、自己实验的方式整理了一遍,这才对 Hystrix 的配置有了一定的了解。

在了解这些配置项的过程中,我也发现了很多坑,平常我们使用中认为理所应当的值并不会让 Hystrix 如期望工作,没有经过斟酌就复制粘贴的配置会让 Hystrix 永远不会起作用。于是写下本文,希望能帮助小伙伴们掌握 Hystrix。如果想了解 Hystrix 的话,可以搭配我之前的分享 PPT:Hystrix 源码解析

文章欢迎转载,请尊重作者劳动成果,带上原文链接:https://www.cnblogs.com/zhenbianshu/p/9630167.html

HystrixCommand


配置方式

我们的配置都是基于 HystrixCommand 的,我们通过在方法上添加 @HystrixCommand 注解并配置注解的参数来实现配置,但有的时候一个类里面会有多个 Hystrix 方法,每个方法都是类似配置的话会冗余很多代码,这时候我们可以在类上使用 @DefaultProperties 注解来给整个类的 Hystrix 方法设置一个默认值。

配置项

下面是 HystrixCommand 支持的参数,除了 commandKey/observableExecutionMode/fallbackMethod 外,都可以使用 @DefaultProperties 配置默认值。

  • commandKey:用来标识一个 Hystrix 命令,默认会取被注解的方法名。需要注意:Hystrix 里同一个键的唯一标识并不包括 groupKey,建议取一个独一二无的名字,防止多个方法之间因为键重复而互相影响。

  • groupKey:一组 Hystrix 命令的集合, 用来统计、报告,默认取类名,可不配置。

  • threadPoolKey:用来标识一个线程池,如果没设置的话会取 groupKey,很多情况下都是同一个类内的方法在共用同一个线程池,如果两个共用同一线程池的方法上配置了同样的属性,在第一个方法被执行后线程池的属性就固定了,所以属性会以第一个被执行的方法上的配置为准。

  • commandProperties:与此命令相关的属性。

  • threadPoolProperties:与线程池相关的属性,

  • observableExecutionMode:当 Hystrix 命令被包装成 RxJava 的 Observer 异步执行时,此配置指定了 Observable 被执行的模式,默认是 ObservableExecutionMode.EAGER,Observable 会在被创建后立刻执行,而 ObservableExecutionMode.EAGER模式下,则会产生一个 Observable 被 subscribe 后执行。我们常见的命令都是同步执行的,此配置项可以不配置。

  • ignoreExceptions:默认 Hystrix 在执行方法时捕获到异常时执行回退,并统计失败率以修改熔断器的状态,而被忽略的异常则会直接抛到外层,不会执行回退方法,也不会影响熔断器的状态。

  • raiseHystrixExceptions:当配置项包括 HystrixRuntimeException 时,所有的未被忽略的异常都会被包装成 HystrixRuntimeException,配置其他种类的异常好像并没有什么影响。

  • fallbackMethod:方法执行时熔断、错误、超时时会执行的回退方法,需要保持此方法与 Hystrix 方法的签名和返回值一致。

  • defaultFallback:默认回退方法,当配置 fallbackMethod 项时此项没有意义,另外,默认回退方法不能有参数,返回值要与 Hystrix方法的返回值相同。

commandProperties


配置方式

Hystrix 的命令属性是由 @HystrixProperty 注解数组构成的,HystrixProperty 由 name 和 value 两个属性,数据类型都是字符串。

以下将所有的命令属性分组来介绍。

线程隔离(Isolation)

  • execution.isolation.strategy: 配置请求隔离的方式,有 threadPool(线程池,默认)和 semaphore(信号量)两种,信号量方式高效但配置不灵活,我们一般采用 Java 里常用的线程池方式。

  • execution.timeout.enabled:是否给方法执行设置超时,默认为 true。

  • execution.isolation.thread.timeoutInMilliseconds:方法执行超时时间,默认值是 1000,即 1秒,此值根据业务场景配置。

  • execution.isolation.thread.interruptOnTimeout: execution.isolation.thread.interruptOnCancel:是否在方法执行超时/被取消时中断方法。需要注意在 JVM 中我们无法强制中断一个线程,如果 Hystrix 方法里没有处理中断信号的逻辑,那么中断会被忽略。

  • execution.isolation.semaphore.maxConcurrentRequests:默认值是 10,此配置项要在 execution.isolation.strategy 配置为 semaphore 时才会生效,它指定了一个 Hystrix 方法使用信号量隔离时的最大并发数,超过此并发数的请求会被拒绝。信号量隔离的配置就这么一个,也是前文说信号量隔离配置不灵活的原因。

统计器(Metrics)

滑动窗口: Hystrix 的统计器是由滑动窗口来实现的,我们可以这么来理解滑动窗口:一位乘客坐在正在行驶的列车的靠窗座位上,列车行驶的公路两侧种着一排挺拔的白杨树,随着列车的前进,路边的白杨树迅速从窗口滑过,我们用每棵树来代表一个请求,用列车的行驶代表时间的流逝,那么,列车上的这个窗口就是一个典型的滑动窗口,这个乘客能通过窗口看到的白杨树就是 Hystrix 要统计的数据。

: bucket 是 Hystrix 统计滑动窗口数据时的最小单位。同样类比列车窗口,在列车速度非常快时,如果每掠过一棵树就统计一次窗口内树的数据,显然开销非常大,如果乘客将窗口分成十分,列车前进行时每掠过窗口的十分之一就统计一次数据,开销就完全可以接受了。 Hystrix 的 bucket (桶)也就是窗口 N分之一 的概念。

  • metrics.rollingStats.timeInMilliseconds:此配置项指定了窗口的大小,单位是 ms,默认值是 1000,即一个滑动窗口默认统计的是 1s 内的请求数据。

  • metrics.healthSnapshot.intervalInMilliseconds:它指定了健康数据统计器(影响 Hystrix 熔断)中每个桶的大小,默认是 500ms,在进行统计时,Hystrix 通过 metrics.rollingStats.timeInMilliseconds / metrics.healthSnapshot.intervalInMilliseconds 计算出桶数,在窗口滑动时,每滑过一个桶的时间间隔时就统计一次当前窗口内请求的失败率。

  • metrics.rollingStats.numBuckets:Hystrix 会将命令执行的结果类型都统计汇总到一块,给上层应用使用或生成统计图表,此配置项即指定了,生成统计数据流时滑动窗口应该拆分的桶数。此配置项最易跟上面的 metrics.healthSnapshot.intervalInMilliseconds 搞混,认为此项影响健康数据流的桶数。 此项默认是 10,并且需要保持此值能被 metrics.rollingStats.timeInMilliseconds 整除。

  • metrics.rollingPercentile.enabled:是否统计方法响应时间百分比,默认为 true 时,Hystrix 会统计方法执行的 1%,10%,50%,90%,99% 等比例请求的平均耗时用以生成统计图表。

  • metrics.rollingPercentile.timeInMilliseconds:统计响应时间百分比时的窗口大小,默认为 60000,即一分钟。

  • metrics.rollingPercentile.numBuckets:统计响应时间百分比时滑动窗口要划分的桶用,默认为6,需要保持能被metrics.rollingPercentile.timeInMilliseconds 整除。

  • metrics.rollingPercentile.bucketSize:统计响应时间百分比时,每个滑动窗口的桶内要保留的请求数,桶内的请求超出这个值后,会覆盖最前面保存的数据。默认值为 100,在统计响应百分比配置全为默认的情况下,每个桶的时间长度为 10s = 60000ms / 6,但这 10s 内只保留最近的 100 条请求的数据。

熔断器(Circuit Breaker)

  • circuitBreaker.enabled:是否启用熔断器,默认为 true;

  • circuitBreaker.forceOpen: circuitBreaker.forceClosed:是否强制启用/关闭熔断器,强制启用关闭都想不到什么应用的场景,保持默认值,不配置即可。

  • circuitBreaker.requestVolumeThreshold:启用熔断器功能窗口时间内的最小请求数。试想如果没有这么一个限制,我们配置了 50% 的请求失败会打开熔断器,窗口时间内只有 3 条请求,恰巧两条都失败了,那么熔断器就被打开了,5s 内的请求都被快速失败。此配置项的值需要根据接口的 QPS 进行计算,值太小会有误打开熔断器的可能,值太大超出了时间窗口内的总请求数,则熔断永远也不会被触发。建议设置为 QPS * 窗口秒数 * 60%

  • circuitBreaker.errorThresholdPercentage:在通过滑动窗口获取到当前时间段内 Hystrix 方法执行的失败率后,就需要根据此配置来判断是否要将熔断器打开了。 此配置项默认值是 50,即窗口时间内超过 50% 的请求失败后会打开熔断器将后续请求快速失败。

  • circuitBreaker.sleepWindowInMilliseconds:熔断器打开后,所有的请求都会快速失败,但何时服务恢复正常就是下一个要面对的问题。熔断器打开时,Hystrix 会在经过一段时间后就放行一条请求,如果这条请求执行成功了,说明此时服务很可能已经恢复了正常,那么会将熔断器关闭,如果此请求执行失败,则认为服务依然不可用,熔断器继续保持打开状态。此配置项指定了熔断器打开后经过多长时间允许一次请求尝试执行,默认值是 5000。

其他(Context/Fallback)

  • requestCache.enabled:是否启用请求结果缓存。默认是 true,但它并不意味着我们的每个请求都会被缓存。缓存请求结果和从缓存中获取结果都需要我们配置 cacheKey,并且在方法上使用 @CacheResult 注解声明一个缓存上下文。

  • requestLog.enabled:是否启用请求日志,默认为 true。

  • fallback.enabled:是否启用方法回退,默认为 true 即可。

  • fallback.isolation.semaphore.maxConcurrentRequests:回退方法执行时的最大并发数,默认是10,如果大量请求的回退方法被执行时,超出此并发数的请求会抛出 REJECTED_SEMAPHORE_FALLBACK 异常。

threadPoolProperties


配置方式

线程池的配置也是由 HystrixProperty 数组构成,配置方式与命令属性一致。

配置项

  • coreSize:核心线程池的大小,默认值是 10,一般根据 QPS * 99% cost + redundancy count 计算得出。

  • allowMaximumSizeToDivergeFromCoreSize:是否允许线程池扩展到最大线程池数量,默认为 false;

  • maximumSize:线程池中线程的最大数量,默认值是 10,此配置项单独配置时并不会生效,需要启用 allowMaximumSizeToDivergeFromCoreSize 项。

  • maxQueueSize:作业队列的最大值,默认值为 -1,设置为此值时,队列会使用 SynchronousQueue,此时其 size 为0,Hystrix 不会向队列内存放作业。如果此值设置为一个正的 int 型,队列会使用一个固定 size 的 LinkedBlockingQueue,此时在核心线程池内的线程都在忙碌时,会将作业暂时存放在此队列内,但超出此队列的请求依然会被拒绝。

  • queueSizeRejectionThreshold:由于 maxQueueSize 值在线程池被创建后就固定了大小,如果需要动态修改队列长度的话可以设置此值,即使队列未满,队列内作业达到此值时同样会拒绝请求。此值默认是 5,所以有时候只设置了 maxQueueSize 也不会起作用。

  • keepAliveTimeMinutes:由上面的 maximumSize,我们知道,线程池内核心线程数目都在忙碌,再有新的请求到达时,线程池容量可以被扩充为到最大数量,等到线程池空闲后,多于核心数量的线程还会被回收,此值指定了线程被回收前的存活时间,默认为 2,即两分钟。

工作方式

Hystrix 内线程池的使用是基于 Java 内置线程池的简单包装,通常有以下三种状态:

  • 如果请求量少,达不到 coreSize,通常会使用核心线程来执行任务。
  • 如果设置了 maxQueueSize,当请求数超过了 coreSize, 通常会把请求放到 queue 里,待核心线程有空闲时消费。
  • 如果 queue 长度无法存储请求,则会创建新线程执行直到达到 maximumSize 最大线程数,多出核心线程数的线程会在空闲时回收。

小结


排查配置问题本身也是学习的过程,了解 Hystrix 源码的过程中也学到了不少 Java 线程池相关的知识,嗯,收获不小。

关于本文有什么问题可以在下面留言交流,如果您觉得本文对您有帮助,可以点击下面的 推荐 支持一下我,博客一直在更新,欢迎 关注

 

一、什么情况下会触发fallback方法?
名字

描述

触发fallback

EMIT

值传递

NO

SUCCESS

执行完成,没有错误

NO

FAILURE

执行抛出异常

YES

TIMEOUT

执行开始,但没有在允许的时间内完成

YES

BAD_REQUEST

执行抛出HystrixBadRequestException

NO

SHORT_CIRCUITED

断路器打开,不尝试执行

YES

THREAD_POOL_REJECTED

线程池拒绝,不尝试执行

YES

SEMAPHORE_REJECTED

信号量拒绝,不尝试执行

YES

 

二、fallback方法在什么情况下会抛出异常
名字

描述

抛异常

FALLBACK_EMIT

Fallback值传递

NO

FALLBACK_SUCCESS

Fallback执行完成,没有错误

NO

FALLBACK_FAILURE

Fallback执行抛出出错

YES

FALLBACK_REJECTED

Fallback信号量拒绝,不尝试执行

YES

FALLBACK_MISSING

没有Fallback实例

YES

 

三、hystrix dashboard界面监控参数
 

四、配置信息(default或HystrixCommandKey)最常用的几项
超时时间(默认1000ms,单位:ms) 

(1)hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds

在调用方配置,被该调用方的所有方法的超时时间都是该值,优先级低于下边的指定配置

(2)hystrix.command.HystrixCommandKey.execution.isolation.thread.timeoutInMilliseconds

在调用方配置,被该调用方的指定方法(HystrixCommandKey方法名)的超时时间是该值

线程池核心线程数

hystrix.threadpool.default.coreSize(默认为10)

Queue

(1)hystrix.threadpool.default.maxQueueSize(最大排队长度。默认-1,使用SynchronousQueue。其他值则使用 LinkedBlockingQueue。如果要从-1换成其他值则需重启,即该值不能动态调整,若要动态调整,需要使用到下边这个配置)

(2)hystrix.threadpool.default.queueSizeRejectionThreshold(排队线程数量阈值,默认为5,达到时拒绝,如果配置了该选项,队列的大小是该队列)

注意:如果maxQueueSize=-1的话,则该选项不起作用

断路器

(1)hystrix.command.default.circuitBreaker.requestVolumeThreshold(当在配置时间窗口内达到此数量的失败后,进行短路。默认20个)

For example, if the value is 20, then if only 19 requests are received in the rolling window (say a window of 10 seconds) the circuit will not trip open even if all 19 failed.

简言之,10s内请求失败数量达到20个,断路器开。

(2)hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds(短路多久以后开始尝试是否恢复,默认5s)

(3)hystrix.command.default.circuitBreaker.errorThresholdPercentage(出错百分比阈值,当达到此阈值后,开始短路。默认50%)

fallback

hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests(调用线程允许请求HystrixCommand.GetFallback()的最大数量,默认10。超出时将会有异常抛出,注意:该项配置对于THREAD隔离模式也起作用)

 

五、属性配置参数
参数说明英文地址:https://github.com/Netflix/Hystrix/wiki/Configuration

 

HystrixProperty参考代码地址:http://www.programcreek.com/java-api-examples/index.php?source_dir=Hystrix-master/hystrix-contrib/hystrix-javanica/src/test/java/com/netflix/hystrix/contrib/javanica/test/common/configuration/command/BasicCommandPropertiesTest.java

 

(一)Command Properties
以下属性控制HystrixCommand行为:

1、Execution
以下属性控制HystrixCommand.run()如何执行。

 

参数

描述

默认值

execution.isolation.strategy

隔离策略,有THREAD和SEMAPHORE

THREAD - 它在单独的线程上执行,并发请求受线程池中的线程数量的限制
SEMAPHORE - 它在调用线程上执行,并发请求受到信号量计数的限制

默认使用THREAD模式,以下几种场景可以使用SEMAPHORE模式:

只想控制并发度

外部的方法已经做了线程隔离

调用的是本地方法或者可靠度非常高、耗时特别小的方法(如medis)

 

execution.isolation.thread.timeoutInMilliseconds

超时时间

默认值:1000

在THREAD模式下,达到超时时间,可以中断

在SEMAPHORE模式下,会等待执行完成后,再去判断是否超时

设置标准:

有retry,99meantime+avg meantime

没有retry,99.5meantime

 

execution.timeout.enabled

HystrixCommand.run()执行是否应该有超时。

默认值:true

execution.isolation.thread.interruptOnTimeout

在发生超时时是否应中断HystrixCommand.run()执行。

默认值:true

THREAD模式有效

execution.isolation.thread.interruptOnCancel

当发生取消时,执行是否应该中断。

默认值为false

THREAD模式有效

execution.isolation.semaphore.maxConcurrentRequests

设置在使用时允许到HystrixCommand.run()方法的最大请求数。

默认值:10

SEMAPHORE模式有效

 

2、Fallback
以下属性控制HystrixCommand.getFallback()如何执行。这些属性适用于ExecutionIsolationStrategy.THREAD和ExecutionIsolationStrategy.SEMAPHORE。

参数

描述

默认值

fallback.isolation.semaphore.maxConcurrentRequests

设置从调用线程允许HystrixCommand.getFallback()方法的最大请求数。

SEMAPHORE模式有效

默认值:10

fallback.enabled

确定在发生失败或拒绝时是否尝试调用HystrixCommand.getFallback()。

默认值为true

 

3、Circuit Breaker
断路器属性控制HystrixCircuitBreaker的行为。

 

参数

描述

默认值

circuitBreaker.enabled

确定断路器是否用于跟踪运行状况和短路请求(如果跳闸)。

默认值为true

circuitBreaker.requestVolumeThreshold

熔断触发的最小个数/10s

默认值:20

circuitBreaker.sleepWindowInMilliseconds

熔断多少秒后去尝试请求

默认值:5000

circuitBreaker.errorThresholdPercentage

失败率达到多少百分比后熔断

默认值:50

主要根据依赖重要性进行调整

 

circuitBreaker.forceOpen

 

属性如果为真,强制断路器进入打开(跳闸)状态,其中它将拒绝所有请求。

默认值为false

此属性优先于circuitBreaker.forceClosed

circuitBreaker.forceClosed

该属性如果为真,则迫使断路器进入闭合状态,其中它将允许请求,而不考虑误差百分比。

默认值为false

如果是强依赖,应该设置为true

circuitBreaker.forceOpen属性优先,因此如果forceOpen设置为true,此属性不执行任何操作。

 

4、Metrics
以下属性与从HystrixCommand和HystrixObservableCommand执行捕获指标有关。

参数

描述

默认值

metrics.rollingStats.timeInMilliseconds

此属性设置统计滚动窗口的持续时间(以毫秒为单位)。对于断路器的使用和发布Hystrix保持多长时间的指标。

默认值:10000

metrics.rollingStats.numBuckets

此属性设置rollingstatistical窗口划分的桶数。

以下必须为true - “metrics.rollingStats.timeInMilliseconds%metrics.rollingStats.numBuckets == 0” -否则将抛出异常。

默认值:10

metrics.rollingPercentile.enabled

此属性指示是否应以百分位数跟踪和计算执行延迟。 如果禁用它们,则所有摘要统计信息(平均值,百分位数)都将返回-1。

默认值为true

metrics.rollingPercentile.timeInMilliseconds

 

此属性设置滚动窗口的持续时间,其中保留执行时间以允许百分位数计算,以毫秒为单位。

默认值:60000

metrics.rollingPercentile.numBuckets

此属性设置rollingPercentile窗口将划分的桶的数量。

以下内容必须为true - “metrics.rollingPercentile.timeInMilliseconds%metrics.rollingPercentile.numBuckets == 0” -否则将抛出异常。

默认值:6

metrics.rollingPercentile.bucketSize

此属性设置每个存储桶保留的最大执行次数。如果在这段时间内发生更多的执行,它们将绕回并开始在桶的开始处重写。

默认值:100

metrics.healthSnapshot.intervalInMilliseconds

此属性设置在允许计算成功和错误百分比并影响断路器状态的健康快照之间等待的时间(以毫秒为单位)。

默认值:500

 

5、Request Context
这些属性涉及HystrixCommand使用的HystrixRequestContext功能。

 

参数

描述

默认值

requestCache.enabled

HystrixCommand.getCacheKey()是否应与HystrixRequestCache一起使用,以通过请求范围的缓存提供重复数据删除功能。

默认值为true

requestLog.enabled

HystrixCommand执行和事件是否应记录到HystrixRequestLog。

默认值为true

 

 

(二)Collapser Properties
下列属性控制HystrixCollapser行为。

参数

描述

默认值

maxRequestsInBatch

 

此属性设置在触发批处理执行之前批处理中允许的最大请求数。

Integer.MAX_VALUE

timerDelayInMilliseconds

 

此属性设置创建批处理后触发其执行的毫秒数。

默认值:10

requestCache.enabled

 

此属性指示是否为HystrixCollapser.execute()和HystrixCollapser.queue()调用启用请求高速缓存。

默认值:true

 

(三)ThreadPool Properties
以下属性控制Hystrix命令在其上执行的线程池的行为。

大多数时候,默认值为10的线程会很好(通常可以做得更小)。

 

参数

描述

默认值

coreSize

线程池coreSize

默认值:10

设置标准:qps*99meantime+breathing room

maximumSize

此属性设置最大线程池大小。 这是在不开始拒绝HystrixCommands的情况下可以支持的最大并发数。 请注意,此设置仅在您还设置allowMaximumSizeToDivergeFromCoreSize时才会生效。

默认值:10

maxQueueSize

请求等待队列

默认值:-1

如果使用正数,队列将从SynchronizeQueue改为LinkedBlockingQueue

queueSizeRejectionThreshold

此属性设置队列大小拒绝阈值 - 即使未达到maxQueueSize也将发生拒绝的人为最大队列大小。 此属性存在,因为BlockingQueue的maxQueueSize不能动态更改,我们希望允许您动态更改影响拒绝的队列大小。

默认值:5

注意:如果maxQueueSize == -1,则此属性不适用。

keepAliveTimeMinutes

此属性设置保持活动时间,以分钟为单位。

默认值:1

allowMaximumSizeToDivergeFromCoreSize

此属性允许maximumSize的配置生效。 那么该值可以等于或高于coreSize。 设置coreSize <maximumSize会创建一个线程池,该线程池可以支持maximumSize并发,但在相对不活动期间将向系统返回线程。 (以keepAliveTimeInMinutes为准)

默认值:false

metrics.rollingStats.timeInMilliseconds

此属性设置statistical rolling窗口的持续时间(以毫秒为单位)。 这是为线程池保留多长时间。

默认值:10000

metrics.rollingStats.numBuckets

此属性设置滚动统计窗口划分的桶数。
注意:以下必须为true - “metrics.rollingStats.timeInMilliseconds%metrics.rollingStats.numBuckets == 0” -否则将引发异常。

默认值:10

 

 

(四)其他
 

参数

描述

默认值

groupKey

表示所属的group,一个group共用线程池

默认值:getClass().getSimpleName();

commandKey

 

默认值:当前执行方法名

 
————————————————
版权声明:本文为CSDN博主「IT桐桐」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tongtong_use/article/details/78611225

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章