通过Hystrix了解分布式接口级的高可用
前言
分布式系统保障接口级高可用的几种常见方式:限流、熔断、降级。
Hystrix是Netflix开源的一个Java框架,提供了保障接口级高可用相关的各种各样的功能。
Hystrix初览
Hystrix官网对该框架能解决的核心问题已经做了概述,我这里再引用官方的几张图片来讲一讲:
首先,复杂分布式系统中的各个服务之间都是相互依赖的,每个依赖服务在某些时候都不可避免的会失败,正常情况下,应该是下面这样:
但是,当其中某个服务出现问题时,可能阻塞用户请求,如果请求没有与这些依赖故障隔离,那么它有可能被他们拖垮,如下图所示:
在高并发的情况下,一个后端依赖服务的故障,更可能导致服务器上的所有资源在数秒内饱和:
Hystrix的核心功能就是解决上述这种接口层级调用引起的资源耗尽和雪崩问题。
设计原则
我们再来看下Hystrix框架的一些设计原则:
1.阻止任何一个依赖服务耗尽所有的资源,比如tomcat中的所有线程资源
为每一个依赖服务维护一个独立的线程池,或者是semaphore,当线程池已满时,直接拒绝对这个服务的调用。
2.避免请求排队和积压,采用限流和fail fast来控制故障
对于超出阈值的服务调用,直接进行超时,不允许其阻塞过长时间,这个超时时间默认是99.5%的访问时间,也可以自己配置。
3.提供fallback降级机制来应对故障
如果对一个依赖服务的调用失败次数超过了一定的阈值,自动进行熔断,在一定时间内对该服务的调用直接降级,一段时间后再自动尝试恢复。
4.使用资源隔离技术,比如bulkhead(舱壁隔离技术)、swimlane(泳道技术)、circuit breaker(短路技术),来限制任何一个依赖服务的故障影响
通过HystrixCommand
或者HystrixObservableCommand
来封装对外部依赖的访问请求,这个访问请求一般会运行在独立的线程中,资源隔离。
5.通过近实时的统计/监控/报警功能,来提高故障发现的速度
统计对依赖服务的调用成功次数、失败次数、拒绝次数、超时次数。
6.通过近实时的属性和配置热修改功能,来提高故障处理和恢复的速度
对属性和配置的修改提供近实时的支持。
7.保护对依赖服务调用的所有故障情况,而不仅仅只是网络故障情况
当一个服务调用出现失败、被拒绝、超时、短路等异常情况时,自动调用fallback降级机制。
Hystrix能做什么?
在通过第三方客户端访问(通常是通过网络)依赖服务出现高延迟或者失败时,为系统提供保护和控制
在分布式系统中防止级联失败
快速失败(Fail fast)同时能快速恢复
提供失败回退(Fallback)和优雅的服务降级机制
提供近实时的监控、报警和运维控制手段
Hystrix的资源隔离
Hystrix采用了依赖隔离的方式,也可以称为为"舱壁隔离"。
什么是舱壁隔离
可以用轮船的舱壁设计来举例,轮船底下船舱一个个都是互相隔离的,这样一旦哪个舱壁出现漏水也影响不到其他的船舱,Hystrix也是一样,他为每一个需要被调用的服务维护了一个独立的线程池,这样每个服务都有自己的使用资源,当某个服务出现问题时,大家互不影响。
货船为了进行防止漏水和火灾的扩散,会将货仓分隔为多个,当发生灾害时,将所在货仓进行隔离就可以降低整艘船的风险。
舱壁隔离会影响性能么
会的,毕竟每个服务都要维护了一个自己的线程池,说不影响是假的,不过Hystrix的开发人员也对Hystrix对性能的影响做了测试,隔离所带来的好处比开辟多个线程池会产生的开销大的多,至少用了依赖隔离,安全性和可用性又会大大提升,一个系统要是用都不能用,还谈什么性能。
使用舱壁隔离的优点
-
整个系统的安全性和可用性被提高了,保证一个依赖服务不会被其他服务拖垮
-
当依赖的服务出现错误时,线程池可以及时反馈问题。
-
比起容器级别的线程池清理速度,舱壁隔离采用的独有线程池无疑是快的多,这样也有利于在依赖服务失效后的快速恢复。
-
当引入新的依赖服务的时候,由于是依赖隔离的,其余服务不会被影响,系统可以很流畅的接受新依赖服务。
-
每个线程池还可以有自己的监控信息,可以针对想对应的依赖服务反应出这种变化
-
每个线程池还可以有自己内置的并发实现,这样可以为同步的依赖服务,构建异步访问。
Hystrix的资源隔离策略有两种,分别为:线程池和信号量。