服务雪崩效应
- 在微服务架构中通常会有多个服务调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。
- 服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。

服务雪崩效应形成的原因及应对策略
原因 |
描述 |
应对策略 |
硬件故障 |
如服务器宕机,机房断电,光纤被挖断等 |
多机房容灾、异地多活等。 |
程序Bug |
如程序逻辑导致内存泄漏,JVM长时间FullGC等 |
修改程序bug、及时释放资源等。 |
缓存击穿 |
一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用。 |
缓存预加载、缓存异步加载等。 |
流量激增 |
如异常流量,用户重试,代码逻辑重试加大流量等。 |
服务自动扩容、流量控制(服务限流、关闭重试)等。 |
同步等待 |
服务间采用同步调用模式,同步等待造成的资源耗尽。 |
资源隔离、MQ解耦、不可用服务调用快速失败等。资源隔离通常指不同服务调用采用不同的线程池;不可用服务调用快速失败一般通过熔断器模式结合超时机制实现。 |
小结
- 如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。
- 因此,为了构建稳定、可靠的分布式系统,我们的服务应当具有自我保护能力,当依赖服务不可用时,当前服务启动自我保护功能,从而避免发生雪崩效应。
- 在SpringCloud中,将重点介绍使用Hystrix解决同步等待的雪崩问题。
Hystrix
介绍
Hystrix可以做什么
1.资源隔离
- 货船为了进行防止漏水和火灾的扩散,会将货仓分隔为多个, 这种资源隔离减少风险的方式被称为:Bulkheads(舱壁隔离模式)。
- Hystrix将同样的模式运用到了服务调用者上.如下图所示:
- 资源隔离:在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池。
- 在一个高度服务化的系统中,我们实现的一个业务逻辑通常会依赖多个服务,比如: 商品详情展示服务会依赖商品服务, 价格服务和商品评论服务 如图所示:

- 调用三个依赖服务会共享商品详情服务的线程池。如果其中的商品评论服务不可用, 就会出现线程池里所有线程都因等待响应而被阻塞, 从而造成服务雪崩。如图所示:

- Hystrix通过将每个依赖服务分配独立的线程池进行资源隔离, 从而避免服务雪崩。如下图所示, 当商品评论服务不可用时, 即使商品服务独立分配的20个线程全部处于同步等待状态,也不会影响其他依赖服务的调用。

2.请求熔断
- “断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
- 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open)。这时所有请求会直接失败而不会发送到后端服务。
- 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN)。这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN)。
- Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.

3.服务降级
- 服务降级是当我们的某个微服务响应时间过长,或者不可用了,讲白了也就是那个微服务调用不了了,我们不能把错误信息返回出来,或者让他一直卡在那里,所以要在准备一个对应的策略(一个方法),当发生这种问题的时候我们直接调用这个方法来快速返回这个请求,不让他一直卡在那 。
- Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存,告知后面的请求服务不可用了,不要再来了。

小结
- 服务降级:服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示。会出现服务降级的情况:程序运行异常、超时、服务熔断触发服务降级、线程池/信号量打满也会导致服务降级。
- 服务熔断:类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示。
- 接近实时的监控:服务的降级->进而熔断->恢复调用链路
- 服务限流:秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行。
Hystrix实现服务降级
方式一:@HystrixCommand注解方式
1.服务提供者
1.1业务接口和业务实现中添加方法hystrixTimeout
public interface UserService {
boolean checkUser() throws Exception;
String findFeignTimeOut() throws Exception;
String hystrixTimeout(Integer id) throws Exception;
}
@Service
public class UserServiceImpl implements UserService {
@Override
public boolean checkUser() throws Exception {
return true;
}
@Override
public String findFeignTimeOut() throws Exception {
TimeUnit.SECONDS.sleep(3);
return "模拟当前业务,当前业务的执行需要3秒钟";
}
@Override
public String hystrixTimeout(Integer id) throws Exception {
throw new Exception("发生了异常:" + id);
}
}
1.2控制器中处理/provider/hystrix/timeout/{id}请求
@RestController
@Slf4j
public class UserController