熔断机制hystrix

1、问题产生

雪崩效应:是一种因服务提供者的不可用致使服务调用者的不可用,并将不可用逐渐放大的过程java

  正常状况下的服务git

某一服务出现异常,拖垮整个服务链路,消耗整个线程队列,形成服务不可用,资源耗尽:github

    

     造成过程:

           1)服务提供者不可用    

                             a)硬件故障:硬件损坏形成的服务器主机宕机, 网络硬件故障形成的服务提供者的不可访问segmentfault

                             b)程序Bug:后端

                             c)   缓存击穿:缓存击穿通常发生在缓存应用重启, 全部缓存被清空时,以及短期内大量缓存失效时. 大量的缓存不命中, 使请求直击后端,形成服务提供者超负荷运行,引发服务不可用缓存

                             d)用户大量请求:在秒杀和大促开始前,若是准备不充分,用户发起大量请求也会形成服务提供者的不可用服务器

           2)重试加大流量

                             a)用户重试:在服务提供者不可用后, 用户因为忍受不了界面上长时间的等待,而不断刷新页面甚至提交表单网络

                             b)代码逻辑重试: 服务调用端的会存在大量服务异常后的重试逻辑并发

           3)服务调用者不可用

                         a)同步等待形成的资源耗尽:当服务调用者使用同步调用 时, 会产生大量的等待线程占用系统资源. 一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 因而服务雪崩效应产生了。app

2、概念

  1. 服务熔断
              通常是指软件系统中,因为某些缘由使得服务出现了过载现象,为防止形成整个系统故障,从而采用的一种保护措施,因此不少地方把熔断亦称为过载保护。不少时候刚开始可能只是系统出现了局部的、小规模的故障,然而因为种种缘由,故障影响的范围愈来愈大,最终致使了全局性的后果。
    适用场景:防止应用程序直接调用那些极可能会调用失败的远程服务或共享资源
  2. 服务降级:
              当服务器压力剧增的状况下,根据当前业务状况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。

3、工做原理

       Hystrix 是一个帮助解决分布式系统交互时超时处理和容错的类库, 它一样拥有保护系统的能力。Netflix的众多开源项目之一。

     1. 隔离

           Hystrix隔离方式采用线程/信号的方式,经过隔离限制依赖的并发量和阻塞扩散

            1)线程隔离

            Hystrix在用户请求和服务之间加入了线程池。

            Hystrix为每一个依赖调用分配一个小的线程池,若是线程池已满调用将被当即拒绝,默认不采用排队.加速失败断定时间。线程数是能够被设定的。

            原理:用户的请求将再也不直接访问服务,而是经过线程池中的空闲线程来访问服务,若是线程池已满,则会进行降级处理,用户的请求不会被阻塞,至少能够看到一个执行结果(例如返回友好的提示信息),而不是无休止的等待或者看到系统崩溃。

隔离前:

            

     

 

隔离后:

     b)信号隔离:

         信号隔离也能够用于限制并发访问,防止阻塞扩散, 与线程隔离最大不一样在于执行依赖代码的线程依然是请求线程(该线程须要经过信号申请, 若是客户端是可信的且能够快速返回,可使用信号隔离替换线程隔离,下降开销。信号量的大小能够动态调整, 线程池大小不能够。(参考文章2)

 

     2. 熔断

若是某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。若是目标服务状况好转则恢复调用。

熔断器:Circuit Breaker

      熔断器是位于线程池以前的组件。用户请求某一服务以后,Hystrix会先通过熔断器,此时若是熔断器的状态是打开(跳起),则说明已经熔断,这时将直接进行降级处理,不会继续将请求发到线程池熔断器至关于在线程池以前的一层屏障。每一个熔断器默认维护10个bucket ,每秒建立一个bucket ,每一个blucket记录成功,失败,超时,拒绝的次数。当有新的bucket被建立时,最旧的bucket会被抛弃。

         熔断器的状态机:

           

  • Closed:熔断器关闭状态,调用失败次数积累,到了阈值(或必定比例)则启动熔断机制;
  • Open:熔断器打开状态,此时对下游的调用都内部直接返回错误,不走网络,但设计了一个时钟选项,默认的时钟达到了必定时间(这个时间通常设置成平均故障处理时间,也就是MTTR),到了这个时间,进入半熔断状态;
  • Half-Open:半熔断状态,容许定量的服务请求,若是调用都成功(或必定比例)则认为恢复了,关闭熔断器,不然认为还没好,又回到熔断器打开状态; 

4、流程

流程说明:
1 :每次调用建立一个新的HystrixCommand,把依赖调用封装在run()方法中。
2 :执行execute()/queue作同步或异步调用。
3 :判断熔断器(circuit-breaker)是否打开,若是打开跳到步骤 8, 进行降级策略,若是关闭进入步骤。
4 :判断线程池/队列/信号量是否跑满,若是跑满进入降级步骤 8, 不然继续后续步骤。
5 :调用HystrixCommand的run方法。运行依赖逻辑
5a:依赖逻辑调用超时,进入步骤 8。
6 :判断逻辑是否调用成功
6a:返回成功调用结果
6b:调用出错,进入步骤 8。
7 :计算熔断器状态,全部的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态。
8 :getFallback()降级逻辑。
   如下四种状况将触发getFallback调用:
  ( 1 ):run()方法抛出非HystrixBadRequestException异常
  ( 2 ):run()方法调用超时
  ( 3 ):熔断器开启拦截调用
  ( 4 ):线程池/队列/信号量是否跑满
8a:没有实现getFallback的Command将直接抛出异常
8b:fallback降级逻辑调用成功直接返回
8c:降级逻辑调用失败抛出异常
9 :返回执行成功结果

5、执行方式

同步执行:即一旦开始执行该命令,当前线程就得阻塞着直到该命令返回结果,而后才能继续执行下面的逻辑

异步执行:命令开始执行会返回一个Future<T>的对象,不阻塞后面的逻辑,开发者本身根据须要去获取结果。

响应式执行:命令开始执行会返回一个Observable<T> 对象,开发者能够给给Obeservable对象注册上Observer或者Action1对象,响应式地处理命令执行过程当中的不一样阶段。当调用HystrixCommand的observe()方法,或使用Observable的工厂方法(just(),from())即为响应式执行,这个功能的实现是基于Netflix的另外一个开源项目RxJava(https://github.com/Netflix/RxJava)来的,更细节的用法能够参考:https://github.com/Netflix/Hystrix/wiki/How-To-Use#wiki-Reactive-Execution

6、代码实现

jar包:

hystrix包
<dependency>
     <groupId>com.netflix.hystrix</groupId>
     <artifactId>hystrix-core</artifactId>
     <version> 1.4 . 21 </version>
</dependency>
设置参数  展开原码

 

参数
做用
备注

circuitBreaker.errorThresholdPercentage

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

默认值:50

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

circuitBreaker.forceClosed

是否强制关闭熔断 若是是强依赖,应该设置为true

circuitBreaker.requestVolumeThreshold

熔断触发的最小个数/10s 默认值:20

circuitBreaker.sleepWindowInMilliseconds

熔断多少秒后去尝试请求 默认值:5000

commandKey

  默认值:当前执行方法名

coreSize

线程池coreSize

默认值:10

execution.isolation.semaphore.maxConcurrentRequests

信号量最大并发度 SEMAPHORE模式有效,默认值:10

execution.isolation.strategy

隔离策略,有THREAD和SEMAPHORE

默认使用THREAD模式,如下几种可使用SEMAPHORE模式:

  • 只想控制并发度
  • 外部的方法已经作了线程隔离
  • 调用的是本地方法或者可靠度很是高、耗时特别小的方法(如medis)

execution.isolation.thread.interruptOnTimeout

是否打开超时线程中断 THREAD模式有效

execution.isolation.thread.timeoutInMilliseconds

 

超时时间

默认值:1000

在THREAD模式下,达到超时时间,能够中断

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

execution.timeout.enabled

是否打开超时  

fallback.isolation.semaphore.maxConcurrentRequests

fallback最大并发度 默认值:10

groupKey

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

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

maxQueueSize

请求等待队列

默认值:-1

若是使用正数,队列将从SynchronizeQueue改成LinkedBlockingQueue

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被划分的数量  
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds  记录health 快照(用来统计成功和错误绿)的间隔,默认500ms  

 

 展开原码
监控service  展开原码
同步执行  展开原码
异步执行  展开原码

 

7、参考文章

 官方文档:https://github.com/Netflix/Hystrix/wiki

使用Hystrix实现自动降级与依赖隔离

同步异步反应执行三种方式示例:Hystrix使用&设置准则#2.使用

http://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-javanica

http://blog.csdn.net/guwei9111986/article/details/51649240

http://www.javashuo.com/article/p-augpkylg-kt.html

相关文章
相关标签/搜索