天天看点

springcloud之hystrixhystrix

hystrix

  • 加入依赖
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-starter-hystrix</artifactid>
</dependency>
           
  • 启动类上接上注解EnableCircuitBreaker或SpringCloudApplication都可以
  • 在指定方法上添加注解HystrixCommand 然后指定回调方法fallbackMethod

原理

  • 1.创建HystrixCommand或HystrixObservableCommand对象

    • HystrixCommand: 用在依赖的服务返回单个操作结果的时候。

    • HystrixObservableCommand: 用在依赖的服务返回多个操作结果的时候

  • 2:命令执行

    HystrixComrnand实现了下面两个执行方式。

    • execute (): 同步执行,从依赖的服务 返回一 个单 一的结果对象, 或是在发生错误的时候抛出常。

    • queue (): 异步执行,直接返回一 个Future对象, 其中包含了服务 执行 结束时要返回的单一结果对象。

    HystrixObservableCommand实现了另外两种 执行方式。

    • observe () : 返回Observable对象,它代表了操作的多个结果,它是一 个HotObservable。

    • toObservable(): 同样会返回Observable对象, 也代表了操作的多个结果,但它返回的是一 个Cold Observable。

    最主要的是一个订阅者-观察者模式

  • 3 结果是否被缓存

    若当前命令的请求缓存功能是被启用的, 并且该命令缓存命中, 那么缓存的结果会立即以Observable 对象的形式 返回。

  • 4 断路器是否打开

    • 如果断路器是打开的,那么Hystrix不会执行命令,而是转接到fallback处理逻辑(对

    应下面第8步)。

    • 如果断路器是关闭的, 那么Hystrix跳到第5步,检查是否有可用资源来 执行命令。

  • 5 线程池I请求队列I信号量是否占满

    如果与命令相关的线程池和请求队列,或者信号量(不使用线程池的时候)已经被占满, 那么Hystrix也不会执行命令,而是转接到fallback处理逻辑(对应下面第8步)。

  • 6 .HystrixObservableCommand.construct()或HystrixCommand.run()

    • HystrixCommand.run(): 返回 一 个单 一 的结果,或者抛出异常。

    • HystixObservableCommand.construct(): 返回 一 个Observable对象来

    发射多个结果,或通过onError发送错误通知。

  • 7.计算断路器的健康度

    Hystrix会将“成功” 、 “失败” 、 “ 拒绝 ” 、 “超时”等信息报告给断路器,而断路器会维护 一 组计数器来统计这些数据。

    断路器会使用这些统计数据来决定是否要将断路器打开,来对某个依赖服务的请求进行“熔断/短路” ,直到恢复期结束。 若在恢复期结束后,根据统计数据判断如果还是未达到健康指标,就再次“熔断/短路”

  • 8.fallback处理

    能够引起服务降级处理的清况有下面几种:

    • 第4步, 当前命令处于“熔断I短路”状态, 断路器是打开的时候。

    • 第5步, 当前命令的线程池、 请求队列或者信号量被占满的时候。

    • 第6步,Hys红ixObservableCommand.cons七ruct()或HystrixCommand.run()

    抛出异常的时候。在服务降级逻辑中, 我们需要实现一 个通用的响应结果, 并且该结果的处理逻辑应当是从缓存或是根据 一 些静态逻辑来获取,而不是依赖网络请求获取。如果一 定要在降级逻辑中包含网络请求,那么该请求也必须被包装在HystrixCommand或是Hys七江xObservableCommand

    中, 从而形成级联的降级策略, 而最终的降级逻辑 一 定不是 一 个依赖网络请求的处理, 而是 一 个能够稳定地返回结果的处理逻辑

• 当使用HystrixCommand的时候, 通过实现HystrixCommand.getFallback()来实现服务降级逻辑。

• 当使用 HystrixObservableCommand 的时候, 通过 HystrixObservableCommand.resumeWithFallback()实现服务降级逻辑, 该方法会返回 一 个Observable对象来发射 一 个或多个降级结果

如果降级执行发现失败的时候,Hystrix会根据不同的执行方法做出不同的处理

• execu七e(): 抛出异常。

• queue(): 正常返回Fu七ure对象,但是当 调用get()来获取结果的时候会抛出异常。

• observe () : 正常返回Observable对象, 当订阅它的时候, 将立即通过调用订阅者的onError方法来通知中止请求。

• toObservable(): 正常返回Observable对象, 当订阅它的时候, 将通过调用订阅者的onError方法来通知中止请求

  • 9.返回成功的响应

断路器原理

HystrixCircuitBreaker接口主要定义了三个断路器的抽象方法。

• allowRequest (): 每个 Hystrix 命令的请求都通过它判断是否被执行。

@Override
public boolean allowRequest() {
    if (properties.circuitBreakerForceOpen().get()) {
        return false;
    }
    if (properties.circuitBreakerForceClosed().get()) {
        return true;
    }
    if (circuitOpened.get() == -1) {
        return true;
    } else {
        if (status.get().equals(Status.HALF_OPEN)) {
            return false;
        } else {
            return isAfterSleepWindow();
        }
    }
}
           

• isOpen(): 返回当前断路器是否打开。

@Override
public boolean isOpen() {
/**HystrixCommandProperties.circuitBreakerForceOpen = true ( 默认值 :false) 时,即断路器强制打开,返回 false 。当该配置接入配置中心后,可以动态实现打开熔断。为什么会有该配置?当 HystrixCircuitBreaker 创建完成后,无法动态切换 NoOpCircuitBreaker 和 HystrixCircuitBreakerImpl ,通过该配置以实现类似效果 */
    if (properties.circuitBreakerForceOpen().get()) {
        return true;
    }
/**当 HystrixCommandProperties.circuitBreakerForceClose = true ( 默认值 :false) 时,即断路器强制关闭,返回 true */
    if (properties.circuitBreakerForceClosed().get()) {
        return false;
    }
//断路器上一次被打开得时间戳( circuitOpened ) 是否大于0,判断短路器是否打开
    return circuitOpened.get() >= 0;
}
           

• markSuccess(): 用来闭合断路器。

可以参考 https://blog.csdn.net/pfnie/article/details/82317184
  • 依赖隔离

    Hystrix利用舱壁模式(为每一个依赖服务创建一个独立的线程池,隔离对其他服务的影响),也可以使用信号量来控制单个依赖服务的并发度,但是不能实现超时和实现异步访问

    在 HystrixCommand和HystrixObservableCommand中有两处支持信号量的使用。

    • 命令执行:如果将隔离策略参数execution.isolation.strategy设置为

    SEMAPHORE, Hysntrix 会使用信号量替代线程池来控制依赖服务的并发。

    • 降级逻辑:当 Hystrix 尝试降级逻辑时, 它会在调用线程中使用信号量

使用

1.自定义类来继承HystrixCommand

springcloud之hystrixhystrix

• 同步执行: User u = new UserCommand (restTemplate, lL) . execute ();。

• 异步执行: Future futureUser = new UserCommand (restTemplate,lL) .queue() ; 。 异步执行的时候, 可以通过对返回的 futureUser 调用 get 方法来获取结果。

2. 使用注解@HystrixCommand

同步可以直接贴在方法上

springcloud之hystrixhystrix

异步就需要另外定义

springcloud之hystrixhystrix

定义服务降级

fallback 是 Hystrix 命令执行失败时使用的后备方法, 用来实现服务的降级处理逻辑。

在 HystrixCommand 中可以通过重载 getFallback ()方法来实现服务降级逻辑, Hystrix

会在 run() 执行过程中出现错误、 超时、 线程池拒绝、 断路器熔断等情况时, 执行

getFallback ()方法内的逻辑, 比如我们可以在继承HystrixCommand的类中重载 getFallback ():

springcloud之hystrixhystrix

或者是使用注解@HystrixCommand(fallbackMethod = “回调方法”)

回调方法需要放在同一个类中,

异常传播

在 HystrixComrnand 实现的 run() 方法中抛出异常时, 除了 HystriyBadRequesException 之外,其他异常均会被 Hystrix 认为命令执行失败并触发服务降级的处理逻辑,所以当需要在命令执行中抛出不触发服务降级的异常时来使用它。

而在使用注册配置实现 Hystrix 命令时,它还支持忽略指定异常类型功能, 只需要通过设置 @HystrixComrnand 注解的 ignoreExceptions 参数

springcloud之hystrixhystrix

命令名称、 分组以及线程池划分

使用HystrixThreadPoolKey划分每个线程,也可以使用注解的形式

springcloud之hystrixhystrix

请求缓存

  • 开启缓存功能:在实现 HystrixCommand 或HystrixObservableCommand 时, 通过重载 getCacheKey ()方法来开启请求缓存,需要指定一个非null的key
springcloud之hystrixhystrix
  • 优点

    • 减少重复的请求数, 降低依赖服务的并发度。

    • 在同一 用户请求的上下文中, 相同依赖服务的返回数据始终保持 一 致。

    • 请求缓存在 run() 和 construct ()执行之前生效, 所以可以有效减少不必要的线程开销

  • 清理失效缓存功能:通过 HystrixRequestCache.clear() 方法来进行缓存的清理
springcloud之hystrixhystrix
  • cacheKeyMethod要指定缓存key的方法,需要同个类里面.或者使用CacheKey
    springcloud之hystrixhystrix
  • 删除使用CacheRemove
    springcloud之hystrixhystrix
  • 具体的注解使用
  • springcloud之hystrixhystrix

请求合并

  • Hystrix 提供了 HystrixCollapser 来实现请求的合并,以减少通信消耗和线程数的占用
  • 继承HystrixCollapser实现请求合并器
  • 使用注解实现合并器
    springcloud之hystrixhystrix

通过batchMethod 属性指定了批量请求的实现方法为findAll 方法,通过collapserProperties属性为合并请求器设置了相关属性,使用@HystrixProperty(name = “timerDelayinMilliseconds”,value=“100”)将合并时间窗设置为100毫秒

  • 请求合并的额外开销
    • 请求命令本身的延迟
    • 延迟时间窗内的并发量

属性配置

• 全局默认值:如果没有设置下面三个级别的属性, 那么这个属性就是默认值。 由千该属性通过代码定义, 所以对于这个级别, 我们主要关注它在代码中定义的默认值即可。

• 全局配置属性:通过在配置文件中定义全局属性值, 在应用启动时或在与 SpringCloud Config 和 Spring Cloud Bus 实现的动态刷新配置功能配合下,可以实现对“ 全局默认值”的覆盖以及在运行期对

“ 全局默认值 ”的动态调整。

• 实例默认值:通过代码为实例定义的默认值。 通过代码的方式为实例设置属性值来覆盖默认的全局配置。

• 实例配置属性:通过配置文件来为指定的实例进行属性配置, 以覆盖前面的三个默认值。 它也可用Spring Cloud Config和Spring Cloud Bus实现的动态刷新配置功能实现对具体实例配置的动态调整。

  • Execution相关的属性的配置:
    • hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphore
    • hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令执行超时时间,默认1000ms
    • hystrix.command.default.execution.timeout.enabled 执行是否启用超时,默认启用true
    • hystrix.command.default.execution.isolation.thread.interruptOnTimeout 发生超时是是否中断,默认true
    • hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。

      semaphore应该占整个容器(tomcat)的线程池的一小部分。

  • Fallback相关的属性

    这些参数可以应用于Hystrix的THREAD和SEMAPHORE策略

    • hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。默认10
    • hystrix.command.default.fallback.enabled 当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback() 。默认true
  • Circuit Breaker相关的属性
    • hystrix.command.default.circuitBreaker.enabled 用来跟踪circuit的健康性,如果未达标则让request短路。默认true
    • hystrix.command.default.circuitBreaker.requestVolumeThreshold 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发circuit break。默认20
    • hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒绝request,也就是5000毫秒后才会关闭circuit。默认5000
    • hystrix.command.default.circuitBreaker.errorThresholdPercentage错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50
    • hystrix.command.default.circuitBreaker.forceOpen 强制打开熔断器,如果打开这个开关,那么拒绝所有request,默认false
    • hystrix.command.default.circuitBreaker.forceClosed 强制关闭熔断器 如果这个开关打开,circuit将一直关闭且忽略circuitBreaker.errorThresholdPercentage
  • Metrics相关参数
    • hystrix.command.default.metrics.rollingStats.timeInMilliseconds 设置统计的时间窗口值的,毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000
    • hystrix.command.default.metrics.rollingStats.numBuckets 设置一个rolling window被划分的数量,若numBuckets=10,rolling window=10000,那么一个bucket的时间即1秒。必须符合rolling window % numberBuckets == 0。默认10
    • hystrix.command.default.metrics.rollingPercentile.enabled 执行时是否enable指标的计算和跟踪,默认true
    • hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds 设置rolling percentile window的时间,默认60000
    • hystrix.command.default.metrics.rollingPercentile.numBuckets 设置rolling percentile window的numberBuckets。逻辑同上。默认6
    • hystrix.command.default.metrics.rollingPercentile.bucketSize 如果bucket size=100,window=10s,若这10s里有500次执行,只有最后100次执行会被统计到bucket里去。增加该值会增加内存开销以及排序的开销。默认100
    • hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 记录health 快照(用来统计成功和错误绿)的间隔,默认500ms
  • Request Context 相关参数
    • hystrix.command.default.requestCache.enabled 默认true,需要重载getCacheKey(),返回null时不缓存
    • hystrix.command.default.requestLog.enabled 记录日志到HystrixRequestLog,默认true
  • Collapser Properties 相关参数
    • hystrix.collapser.default.maxRequestsInBatch 单次批处理的最大请求数,达到该数量触发批处理,默认Integer.MAX_VALUE
    • hystrix.collapser.default.timerDelayInMilliseconds 触发批处理的延迟,也可以为创建批处理的时间+该值,默认10
    • hystrix.collapser.default.requestCache.enabled 是否对HystrixCollapser.execute() and HystrixCollapser.queue()的cache,默认true
  • ThreadPool 相关参数

    线程数默认值10适用于大部分情况(有时可以设置得更小),如果需要设置得更大,那有个基本得公式可以follow:

    • requests per second at peak when healthy × 99th percentile latency in seconds + some breathing room

      每秒最大支撑的请求数 (99%平均响应时间 + 缓存值)

      比如:每秒能处理1000个请求,99%的请求响应时间是60ms,那么公式是:

      1000 (0.060+0.012)

      基本得原则时保持线程池尽可能小,他主要是为了释放压力,防止资源被阻塞。

      当一切都是正常的时候,线程池一般仅会有1到2个线程激活来提供服务

    • hystrix.threadpool.default.coreSize 并发执行的最大线程数,默认10
    • hystrix.threadpool.default.maxQueueSize BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlcokingQueue。该设置只会在初始化时有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默认-1。
    • hystrix.threadpool.default.queueSizeRejectionThreshold 即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝。因为maxQueueSize不能被动态修改,这个参数将允许我们动态设置该值。if maxQueueSize == -1,该字段将不起作用
    • hystrix.threadpool.default.keepAliveTimeMinutes 如果corePoolSize和maxPoolSize设成一样(默认实现)该设置无效。如果通过plugin(https://github.com/Netflix/Hystrix/wiki/Plugins)使用自定义实现,该设置才有用,默认1.
    • hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds 线程池统计指标的时间,默认10000
    • hystrix.threadpool.default.metrics.rollingStats.numBuckets 将rolling window划分为n个buckets,默认10

监控设置

  • hystriy dashborad,turbine集群监控

继续阅读