Spring Cloud Hystrix 服务容错保护详解

Spring Cloud Hystrix java

工做流程图:缓存

    

流程说明:并发

1.每次调用建立一个新的HystrixCommand或HystrixObservableCommand把依赖调用封装在run()方法中.异步

        HystrixCommand 用在依赖的服务返回单个操做结果的时候ide

        HystrixObservableCommand 用在依赖的服务返回多个操做结果的时候ui

2.执行execute()/queue作同步或异步调用.spa

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

@HystrixCommand(fallbackMethod = "helloFallBack")
	public String helloService() {
		return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody();
	}

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

@HystrixCommand(fallbackMethod = "helloFallBack")
	public Future<String> helloServiceAsync() {
		return new AsyncResult<String>() {
			@Override
			public String invoke() {
				return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody();
			}
		};
	}

             Future提供的方法:rest

                                            get() 该方法阻塞当前,等待计算完成,获取返回结果。

                                            isDone () 若是此任务完成返回true

                                            isCancelled() 任务完成前被取消返回true

                                            cancel(false) 取消任务,未开始或已完成返回false,参数表示是否中断执行中的线程 (true中断,false不中断)

3.结果是否被缓存

    若当前请求的方法缓存功能时被启动的,而且该方法命中了缓存,直接返回缓存中的数据

    ps:Hystrix中的缓存功能,须要初始化HystrixRequestContext = HystrixRequestContext. initializecontext (),每次发起Request时初始化,须要设置一个Filter。以下源码中:HystrixRequestContext是ThreadLocal的,也就是说在一次请求中 屡次调用依赖服务 这个时候缓存功能才有实际意义。若是同时发送两个请求,也是会调用两次依赖服务的。

private static ThreadLocal<HystrixRequestContext> requestVariables = new ThreadLocal<HystrixRequestContext>();

    public static boolean isCurrentThreadInitialized() {
        HystrixRequestContext context = requestVariables.get();
        return context != null && context.state != null;
    }

4.判断熔断器(circuit-breaker)是否打开,若是打开跳到步骤8,进行降级策略,若是关闭进入第五步骤,检查是否有可用的资源来执行命令.

        判断断路器的打开/关闭状态,详细逻辑以下:

         AtomicBoolean circuitOpen(断路器是否打开的标识,默认fasle),若是打开标识为true,标识断路器是打开状态,若是打开直接走降级策略fallBack(),不然就从度量指标对象 (HystrixCommandMetrics 用来记录各种度量指标的对象)中获取HealthCounts统计对象作进一步判断(该对象记录了一个滚动时间窗内的请求信息快照,默认时间窗为10 S)。

             打开熔断器须要知足下面两个条件:

                    1:若是它的请求总数(QPS)在预设的阀值范围内就返回false,标识熔断器处于未打开状态,该阀值的的配置参数为:hystrix.command.default.circuitBreaker.requestVolumeThreshold=20默认值20

                    2:若是错误百分比在阀值范围内就返回false,表示断路器处于未打开状态,该阀值的配置参数为:

hystrix.command.default.circuitBreaker.errorThresholdPercentage=50

                    若是在滚动时间窗内,请求数量超过requestVolumeThreshold的阀值的前提下,若是错误请求数的百分比超过50%,就把断路器设置为打开状态,不然就设置为关闭状态。

                    这里不得不提另外一个参数:hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000 默认值5000,该属性用来设置当断路器打开以后的休眠时间窗,休眠时间结束后,断路器置为“半开”状态,此时再有请求过来的话,不会直接fallback,并且会尝试请求命令,若是依然失败就将断路器继续设置为“打开”的状态,若是成功断路器就设置为“关闭”状态。

5.判断线程池/队列/信号量是否跑满,若是跑满进入降级步骤8,不然继续后续步骤.

        

                若是在请求时,hystrix的线程池和请求队列,或者是信号量(不使用线程池的时候)已经被占满的状况下,Hystrix 也不会执行命令而是转接到fallback处理。

                hystrix指的线程池不是容器的线程池,而是每一个依赖服务的专有线程池,这样作主要是为了当某个依赖服务有问题时,不会影响其余依赖服务,这种模式叫“舱壁模式”。这种模式就和Docker实现进程隔离的模式相同,Docker使得容器和容器直接不会相互影响,而Hystrix则使用该模式实现线程池的隔离。

                   hystrix线程池隔离的优点:

                        1:应用自身获得彻底保护,不会受不可控的依赖服务影响,即使给依赖服务分配的线程池填满,也不会影响应用自身的其余部分。

                        2:能够有效下降接入新服务的风险,当新服务接入时不稳定或存在问题时,不会影响应用其余请求、

                        3:当依赖服务从失效中恢复正常,它的线程池会被清理而且可以立刻恢复健康的服务,比容器级别的清理恢复要快不少。

                        4:线程池提供内置的并发实现,能够利用它为同步的依赖服务构建异步访问。

                     示例:

@HystrixCommand(fallbackMethod = "helloFallBack", commandKey = "helloService", groupKey = "Hello", threadPoolKey = "helloServiceIdThread", 
			threadPoolProperties= {@HystrixProperty(name="coreSize",value="20"),
								   @HystrixProperty(name="maxQueueSize",value="10")})

                        参数说明:coreSize 用来控制核心线程数,也就是最大并发量 默认为10

                                         maxQueueSize 用来控制队列大小,当设置为-1时,线程池将使用SynchronousQueue实现的队列,不然将使用LinkedBlockingQueue实现的队列,默认为-1。

                                         queueSizeRejectionThreshold 该参数用来设置队列的拒绝阀值,即便队列没有达到设置的最大值也能拒绝请求,该参数主要是对LinkedBlockingQueue的补充,由于LinkedBlockingQueue运行时不能动态修改它的大小,而经过该属性就能够调整拒绝请求的队列大小了,默认5。maxQueueSize为-1时无效,由于maxQueueSize为-1时,用的是SynchronousQueue,

                                          timeInMilliseconds 该参数用来设置滚动时间窗的长度,单位为毫秒。该滚动时间窗的长度用于线程池的指标度量,它会被分红多个桶进行统计。默认10000

                                          numBuckets   该参数用来设置滚动时间窗被划为成“桶”的数量,默认10

6.调用HystrixCommand的run方法.运行依赖逻辑 依赖逻辑调用超时,进入步骤8.

            配置参数:

                execution配置控制的是HystrixCommand.run()的执行

                execution.isolation.strategy: 该属性用来设置执行的隔离策略。 1:Thread 线程 2:Semaphore 信号量 ,默认Thread

                execution.isolation.thread.timeoutInMilliseconds该属性用来配置HystrixCommand执行的超时间,若是超时直接进入fallBack,并将命令标记为TIMEOUT 默认值1000毫秒

                execution.timeOut.enabled:该属性用来配置是否启用超时设置,当设置为false时execution.isolation.thread.timeoutInMilliseconds将不起做用。默认为true

                execution.isolation.thread.interruptOntimeout:该属性用来配置当HstrixCommand.run()执行超时是否要将它中断

                execution.isolation.thread.interruptOnCancel:该属性用来配置当HystrixCommand.run()执行被取消时是否要将它中断

                execution.isolation.semaphore.maxConcurrentRequests:当HystrixCommand的隔离策略使用信号量时,用来设置信号量的大小(并发请求数)。当最大的并发数到达阀值时,后续的请求都会被拒绝,默认值10

7.判断逻辑是否调用成功。返回成功调用结果;调用出错,进入步骤8fallback.

                   判断调用成功主要就是看是否超时,是否抛出异常,这里要说的时若是设置了忽略异常,当异常类型是ClassCastException时 是不会触发fallback的,会将异常信息包装在HystrixBadRequestException中抛出。      

                @HystrixCommand(fallbackMethod = "helloFallBack", ignoreExceptions = ClassCastException.class)

8.计算熔断器状态,全部的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态.

        

9.getFallback()降级逻辑。如下四种状况将触发getFallback调用:

  • run()方法抛出非HystrixBadRequestException异常。
  • run()方法调用超时
  • 熔断器开启拦截调用
  • 线程池/队列/信号量是否跑满

没有实现getFallback的Command将直接抛出异常,fallback降级逻辑调用成功直接返回,降级逻辑调用失败抛出异常.

10.返回执行成功结果

 

fallback条件

Name

Description

Triggers Fallback?

执行失败 抛出异常 YES
超时 开始执行,但没有在容许的时间内完成 YES
断路器 断路器打开状态下 YES
线程池拒绝 线程池的容量满了或大于拒绝阀值 YES
信号量拒绝 信号量容量满了 YES

 

任务执行失败,执行超时,依赖熔断,执行线程池满,信号量满会fullback

 

熔断条件

 

熔断器实现三种类型的状态:open、half-open以及closed:

 

熔断执行流程:

 

  • 熔断器开关关闭时, 请求被容许经过熔断器. 若是当前健康情况高于设定阈值, 开关继续保持关闭. 若是当前健康情况低于设定阈值, 开关则切换为打开状态.
  • 当熔断器开关打开时, 请求被禁止经过.

  • 熔断器开关处于打开状态, 通过一段时间后, 熔断器会自动进入半开状态, 这时熔断器只容许一个请求经过. 当该请求调用成功时, 熔断器恢复;失败,将继续保持熔断状态

自动熔断机制

  1. 当外部依赖I访问出错比例达到某个阈值时,自动触发熔断,以后一小段时间duration(可配置)内访问I的请求自动被降级处理,再也不发给A
  2. 过了设定的duration时间后,放过一个请求到依赖I,探测是否恢复正常,若是恢复正常,解除熔断,不然继续保持通讯熔断状态。
相关文章
相关标签/搜索