断路器
在微服务架构的项目中,尤其是中大型项目,肯定会出现一个服务调用其他的服务,其他服务又调用别的服务,服务和服务之间形成了一种链式的调用关系。 当少量请求时,对于整个服务链条是没有过多的影响的。但是假如当某个服务请求量剧增时,可能照成其他调用该服务的服务也出现问题,这种情况可以称为灾难性雪崩效应。
雪崩效应最终的结果就是:服务链条中的某一个服务不可用,导致一系列的服务不可用,最终造成服务逻辑崩溃。这种问题造成的后果,往往是无法预料的。
在Spring Cloud中解决灾难性雪崩效应就是通过Spring Cloud Netflix Hystrix实现的。这是Netflix开源的一款容错框架,作用包含两点:容错和限流。在Spring cloud中处理服务雪崩效应,都需要依赖hystrix组件。
hystrix如何防止灾难性雪崩效应
降级
超时降级、资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据。实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值。保证服务出现问题整个项目还可以继续运行。
熔断
当失败率(如因网络故障/超时造成的失败率高)达到阀值自动触发降级,熔断器触发的快速失败会进行快速恢复,如:当熔断器启动后,每隔5秒,尝试将新的请求发送给Application Service,如果服务可正常执行并返回结果,则关闭熔断器,服务恢复。保证服务出现问题整个项目还可以继续运行。
降级是出错了返回托底数据,而熔断是出错后如果开启了熔断将会一定时间不在访问application service。
有两种条件会触发熔断,可以在配置中指定,分别是单位时间内的错误数和单位时间内的请求失败率,另外可以配置当熔断策略开启后,延迟多久尝试再次请求远程服务。
请求缓存
Hystrix为了降低访问服务的频率,支持将一个请求与返回结果做缓存处理。如果再次请求的URL没有变化,那么Hystrix不会请求服务,而是直接从缓存中将结果返回。这样可以大大降低访问服务的压力。
Hystrix自带缓存。有两个缺点:
- 是一个本地缓存。在集群情况下缓存是不能同步的。
- 不支持第三方缓存容器。Redis,memcached不支持的。所以可以利用spring cache。实现请求缓存。
请求合并
在高并发情况下,通信次数的增加会导致总的通信时间增加,同时,线程池的资源也是有限的,高并发环境会导致有大量的线程处于等待状态,进而导致响应延迟,Hystrix提供了请求合并。
设置请求合并之后,本来一个请求可能5ms就搞定了,但是现在必须再等10ms看看还有没有其他的请求一起的,这样一个请求的耗时就从5ms增加到15ms了,不过,如果我们要发起的命令本身就是一个高延迟的命令,那么这个时候就可以使用请求合并了,因为这个时候时间窗的时间消耗就显得微不足道了,另外高并发也是请求合并的一个非常重要的场景。
隔离
隔离分为线程池隔离和信号量隔离。
-
线程池隔离
没有线程池隔离的时候可能因为某个接口的高并发导致其他接口也不可用,当使用线程池隔离。不同接口有着自己独立的线程池。即使某个线程池都被占用,也不影响其他线程,所以解决了限流问题。缺点请求在线程池中执行,肯定会带来任务调度、排队和上下文切换带来的开销。因为涉及到跨线程,那么也会存在ThreadLocal数据的传递问题。 -
信号量隔离
在该模式下,接收请求和执行下游依赖在同一个线程内完成,不存在线程上下文切换所带来的性能开销,所以大部分场景应该选择信号量模式。可以通过设置maxConcurrentRequests参数,限制对下游的并发调用量,当并发请求数达到阈值时,请求线程可以快速失败,执行降级。实现也很简单,一个简单的计数器,当请求进入熔断器时,执行tryAcquire(),计数器加1,结果大于阈值的话,就返回false,发生信号量拒绝事件,执行降级逻辑。当请求离开熔断器时,执行release(),计数器减1。