个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈
一、前言
分布式系统环境中,服务间类似依赖非常常见,一个业余调用通常依赖多个基础服务。如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服务资源耗尽,无法继续对外提供服务。并且这种不可用可能沿请求调用链向上传递,这种现象称为雪崩效应。
二、雪崩效应
1、常见场景
(1)硬件故障:如服务器宕机,机房断电,光纤被挖断等。
(2)流量激增:如异常流量,重试加大流量等。
(3)缓存穿透:一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用。
(4)程序bug:如程序逻辑导致内存泄漏,JVM长时间FullGC等。
(5)同步等待:服务间采用同步调用模式,同步等待造成的资源耗尽。
2、应对策略
针对造成雪崩效应的不同场景,可以使用不同的应对策略,没有一种通用所有场景的策略。
(1)硬件故障:多机房容灾、异地多活等。
(2)流量激增:服务自动扩容、流量控制(限流、关闭重试)等。
(3)缓存穿透:缓存预加载、缓存异步加载等。
(4)程序bug:修改程序bug、及时释放资源等。
(5)同步等待:资源隔离、MQ解耦。、不可用服务调用快速失败等。资源隔离通常指不同服务调用采取不同的线程池;不可用服务调用快速失败一般通过熔断模式结合超时机制实现。
综上所述,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。因此,为了构建稳定、可靠的分布式系统,我们的服务应当具有自我保护能力,当依赖服务不可用时,当前服务启动自我保护功能,从而避免发生雪崩效应。本文将重点介绍使用Hystrix解决同步等待的雪崩问题。
三、初探Hystrix
Hystrix,中文含义是豪猪,因其背上长满荆棘,从而拥有了自我保护的能力。本文所说的Hystrix是Netflix公司开源的一款容错框架,同样具有自我保护能力。为了实现容错和自我保护,下面我们看看Hystrix如何设计和实现的。
Hystrix设计目标:
- 对来自依赖的延迟和故障进行防护和控制,这些依赖通常都是通过网络访问的。
- 阻止失败并迅速恢复
- 回退并优雅降级
- 提供近实时的监控与告警
Hystrix遵循的设计原则:
- 防止任何单独的依赖耗尽资源(线程)
- 过载立即切断并快速失败,防止排队
- 尽可能提供回退以保护用户免受故障
- 使用隔离技术(例如隔板、泳道和断路器模式)来限制任何一个依赖的影响
- 通过近实时的指标,监控和告警,确保故障被及时发现
- 通过动态修改配置属性,确保故障及时恢复
- 防止整个依赖客户端执行失败,而不仅仅是网络通信
Hystrix如何实现这些设计目标?
- 使用命令模式将所有对外部服务(或依赖关系)的调用包装在HystrixCommand或 HystrixObservableCommand对象中,并将该对象放在单独的线程中执行。
- 每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是让请求排队)。
- 记录请求成功,失败,超时和线程拒绝。
- 服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的所有请求。
- 请求失败,被拒绝,超时或熔断时执行降级逻辑。
- 近实时地监控指标和配置的修改。
四、Hystrix处理流程
(一)Hystrix 整个工作流程如下:
1、构造一个 HystrixCommand或HystrixObservableCommand对象, 用于封装请求,并在构造方法配置请求被执行需要的参数;
2、执行命令, Hystrix 提供了4种执行命令的方法,后面详述;
3、判断是否使用缓存响应请求,若启用了缓存