Hystrix 简单逻辑理解
可以知道再Hystrix 中的方法 run 与 fallback 方法。还有就是断路器功能。
- run方法失败会进入fallback方法
- 无法执行run方法会进入fallback方法 【线程池的调度无法执行】
- fallback执行一定次数后会直接抛出异常,将不在执行fallback方法。
- 断路器开启后将不会执行run方法而直接进入fallback方法。
- 断路器开启是有条件的。
相关通用主要配置
线程组配置详细说明
参考 HystrixThreadPoolProperties 下Setter 设置
HystrixThreadPoolProperties.Setter()
withCoreSize 核心线程数
withMaxQueueSize 最大任务队列容量
此属性配置为 <1 小于1 时使用的是SynchronousQueue,配置为大于1的整数时使用的是LinkedBlockingQueue
需要注意的是SynchronousQueue 与 LinkedBlockingQueue 区别 见百度说明
- 大于0时
取值建议考虑到并发量需要考虑到队列数量 ,当并发数量 大于配置值时会出现错误队列已满 ,错误如下:
Task java.util.concurrent.FutureTask@c3c7722 rejected from
java.util.concurrent.ThreadPoolExecutor@cc9b543[Running, pool size =
1, active threads = 1, queued tasks = 2, completed tasks = 0]queued tasks = 2 内容为实际maxQueueSize 对应配置值
- 小于0时
因为SynchronousQueue 容器原因 需要考虑线程数, 当线程数不够时同样会出现 如上错误类型
Task java.util.concurrent.FutureTask@35f1688a rejected from
java.util.concurrent.ThreadPoolExecutor@27edf295[Running, pool size =
1, active threads = 1, queued tasks = 0, completed tasks = 0]
通常为了保证尽可能的不被拒绝会将 queueSizeRejectionThreshold 与 maxQueueSize 设置为相同。
withQueueSizeRejectionThreshold 任务拒绝的任务队列阈值
- 当maxQueueSize配置为小于1时候,此配置项不生效。
熔断后出错内容
HystrixCommandProperties.Setter()
withFallbackIsolationSemaphoreMaxConcurrentRequests 最大并发降级请求处理上限
单位窗口时间内处理的熔断错误数,
最简单理解就是配置的sleepWindowInMilliseconds时间执行的fallback方法次数;即当超过这个配置值时会出现两种报错
- 第一种
com.netflix.hystrix.exception.HystrixRuntimeException: update fallback execution rejected.
at com.netflix.hystrix.AbstractCommand.handleFallbackRejectionByEmittingError(AbstractCommand.java:1043)
at com.netflix.hystrix.AbstractCommand.getFallbackOrThrowException(AbstractCommand.java:875)
at com.netflix.hystrix.AbstractCommand.handleTimeoutViaFallback(AbstractCommand.java:997)
at com.netflix.hystrix.AbstractCommand.access$500(AbstractCommand.java:60)
at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:609)
at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:601)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1.run(AbstractCommand.java:1142)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:37)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable.run(HystrixContextRunnable.java:57)
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.tick(AbstractCommand.java:1159)
at com.netflix.hystrix.util.HystrixTimer$1.run(HystrixTimer.java:99)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301( ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
此种出现是连续执行时的报错。假设fallbackIsolationSemaphoreMaxConcurrentRequests 为3 并发数量为5时 前两笔错误后正常运行fallback方法而后面两笔则以这种报错方式出现。
来自方法 handleFallbackRejectionByEmittingError
update fallback execution rejected 中的update 为setter 配置中的 CommandKey
- 第二种
java.lang.RuntimeException: Hystrix circuit short-circuited and is OPEN
at com.netflix.hystrix.AbstractCommand.handleShortCircuitViaFallback(AbstractCommand.java:979)
at com.netflix.hystrix.AbstractCommand.applyHystrixSemantics(AbstractCommand.java:557)
at com.netflix.hystrix.AbstractCommand.access$200(AbstractCommand.java:60)
at com.netflix.hystrix.AbstractCommand$4.call(AbstractCommand.java:419)
at com.netflix.hystrix.AbstractCommand$4.call(AbstractCommand.java:413)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.subscribe(Observable.java:10423)
at rx.Observable.subscribe(Observable.java:10390)
at rx.internal.operators.BlockingOperatorToFuture.toFuture(BlockingOperatorToFuture.java:51)
at rx.observables.BlockingObservable.toFuture(BlockingObservable.java:410)
at com.netflix.hystrix.HystrixCommand.queue(HystrixCommand.java:378)
at com.netflix.hystrix.HystrixCommand.execute(HystrixCommand.java:344)
at com.gui.z.ht.StartMain$1.run(StartMain.java:34)
at java.lang.Thread.run(Thread.java:748)
当第一种报错出现一定程度后以这种报错出现。
报错来自 handleShortCircuitViaFallback方法
handleShortCircuitViaFallback 是这两个报错的统一方法。
可以肯定的是这种runtime exception 都是不会执行fallback 方法的。
命令执行部分配置
HystrixCommandProperties.Setter()
withExecutionTimeoutEnabled 是否允许超时
决定HystrixCommand 中run()执行时是否允许超时,只有设置为true的时候,下面提到的“超时时间上限”才会有效
withExecutionTimeoutInMilliseconds 超时时间上限
超时时间上限#
HystrixCommand执行时候超时的最大上限,单位是毫秒,如果命令执行耗时超过此时间值那么会进入降级逻辑。这个配置生效的前提是executionTimeoutEnabled为true
超时会报错
com.netflix.hystrix.exception.HystrixTimeoutException: null
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1.run(AbstractCommand.java:1142)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:37)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable.run(HystrixContextRunnable.java:57)
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.tick(AbstractCommand.java:1159)
at com.netflix.hystrix.util.HystrixTimer$1.run(HystrixTimer.java:99)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Circuit Breaker 断路器部分配置
withCircuitBreakerRequestVolumeThreshold 断路器请求量阈值
此属性设置将使断路器打开的滑动窗口中的最小请求数量。
例如,如果值是20,那么如果在滑动窗口中只接收到19个请求(比如一个10秒的窗口),即使所有19个请求都失败了,断路器也不会打开。
withCircuitBreakerErrorThresholdPercentage 断路器错误百分比阈值
此属性设置一个错误百分比,当请求错误率超过设定值,断路器就会打开。
withCircuitBreakerSleepWindowInMilliseconds 断路器等待窗口时间
属性设置断路器打开后拒绝请求的时间量,每隔一段时间(sleepWindowInMilliseconds,单位是毫秒)允许再次尝试(也就是放行一个请求)确定是否应该关闭断路器。
关于设置问题。为了保证一个周期循环性质的处理逻辑。是需要使用开启断路器的。【要是不开启断路器用hystrix 就没有什么意义了】。而断路器的周期时间就很重要了。需要根据实际情况判断时间设置。为了保证高交易量的通过。通常是业务压力大断路器等待窗口时间短;压力小则时间可以适当延长。