1. 为什么要有熔断器
当服务出现性能问题时,很容易导致服务宕机,进而导致其他服务不可用,这样一直顺着链路走下去就会导致整个系统不可用,就产生了服务雪崩,这样显然是不可行的,为了提高系统的高可用性,就需要在服务出现问题时,不影响其他服务,不会导致整个系统崩溃,所以就有了Hystrix熔断器,来实现在服务出现问题时,对服务进行降级,熔断操作来保证系统的高可用。
2. 如何解决服务雪崩?
首先请求会打在有@HystrixCommand注解的方法上,这个时候Hystrix内部会维护一个默认大小为10的线程池(请求到达时才会创建线程)来处理请求,假如有10个请求已经过来了,这个时候线程池处于饱和状态,当继续有其他请求过来时,只能等待前10个请求处理完成,这个时候被调用的服务有性能问题,就会导致其他请求在被调用服务正常的情况下请求不到,影响到了正常的服务,所以这个时候就可以对有性能问题的服务做降级或者熔断操作。Hystrix提供了一种常用的解决方法:舱壁模式的形式(线程池隔离)使得请求不全都打到一个线程中处理,为特定的方法指定线程池执行,这样当一个服务不可用时,也不会影响到其他服务。
2.1 线程池隔离
线程隔离的优点:
- 应用程序会被完全保护起来,即使依赖的一个服务的线程池满了,也不会影响到应用程序的其他部分。
- 我们给应用程序引入一个新的风险较低的客户端lib的时候,如果发生问题,也是在本lib中,并不会影响到其他内容,因此我们可以大胆的引入新lib库。
- 当依赖的一个失败的服务恢复正常时,应用程序会立即恢复正常的性能。
- 如果我们的应用程序一些参数配置错误了,线程池的运行状况将会很快显示出来,比如延迟、超时、拒绝等。同时可以通过动态属性实时执行来处理纠正错误的参数配置。
- 如果服务的性能有变化,从而需要调整,比如增加或者减少超时时间,更改重试次数,就可以通过线程池指标动态属性修改,而且不会影响到其他调用请求。
- 除了隔离优势外,hystrix拥有专门的线程池可提供内置的并发功能,使得可以在同步调用之上构建异步的外观模式,这样就可以很方便的做异步编程(Hystrix引入了Rxjava异步框架)
尽管线程池提供了线程隔离,客户端底层代码也必须要有超时设置,不能无限制的阻塞以致线程池一直饱和。如果使用的是无界队列的线程池,还有可能会产生OOM
线程隔离的缺点:
- 线程池的主要缺点就是它增加了计算的开销,每个业务请求(被包装成命令)在执行的时候,会涉及到请求排队,调度和上下文切换。不过Netflix公司内部认为线程隔离开销足够小,不会产生重大的成本或性能的影响。
- 对于不依赖网络访问的服务,比如只依赖内存缓存这种情况下,就不适合用线程池隔离技术,而是采用信号量隔离。
3. Hystrix工作原理
- 当调用出现错误时,开启一个时间窗(默认10秒)
- 在这个时间窗内,统计调用次数是否达到最小请求数?
- 如果没有达到,咋重置统计信息,回到第1步,如果没有达到最小请求数即使请求全部失败,也会回到第1步
- 如果达到了,则统计失败的请求数占所有请求数的百分比,是否达到阈值?,达到则跳闸(不在请求对应的服务),没有则重置统计信息,回到第1步
- 如果跳闸,则会开启一个活动窗口(默认5秒),每隔5秒,Hystrix会让一个请求通过,到达出现问题的服务,看是否恢复?如果恢复,重置断路器,回到第1步,如果失败。回到第3步
网友评论