流量控制:避免因为突发流量而导致的服务宕机。
隔离和降级:避免微服务出现雪崩
避免非法的请求进入微服务当中
避免因为服务的重启而导致这些规则的丢失
1. 初始Sentinel
1.1 雪崩问题及解决方案
1.1.1 雪崩问题
微服务中,服务间调用关系错综复杂,一个微服务往往依赖于其它多个微服务。
如图,服务消费者调用服务提供者,如果服务提供者发生了故障,由于当前服务消费者应用的部分业务依赖于服务提供者,导致服务消费者的业务请求会被阻塞,因为服务消费者要等待服务提供者结果的返回,请求被阻塞,用户自然不会得到响应,Tomcat的这个线程也不会释放,因为阻塞它就不会释放Tomcat的连接,于是越来越多的用户请求到来,越来越多的线程会被阻塞,由于Tomcat服务器支持的线程和并发数有限,业务请求一直被阻塞,会导致服务器资源耗尽,从而导致其它业务请求请求不进来,导致当前服务也故障不可用了,形成级联失败,雪崩就发生了 => 一个服务故障导致依赖于它的服务最终也出现故障了,导致依赖于它的服务最终被拖垮
微服务之间会相互调用,微服务调用链路中的某个服务故障,引起整个链路中的所有微服务都不可用,也就是引起整个链路中的所有微服务都无法访问的情况,这就是服务雪崩。?
解决雪崩问题的常见方式有四种:应对服务雪崩的一种微服务链路保护机制
- 前面三种是已经有服务故障了,我该怎么样去避免这个故障传递到其它服务而引起雪崩(3解决 + 1预防):?
如何避免因服务故障而引起的雪崩问题??
超时处理:
- 调用业务时设定超时时间(给业务设定超时时间),如果请求超过一定时间没有响应就释放该请求,直接返回错误信息,而不会让请求无休止等待,这样就不会导致一直占用Tomcat资源,可以在一定程序上缓解雪崩问题{缓解雪崩问题而不是100%解决雪崩问题,因为如果说释放请求的速度没有进入请求的速度快,那么终有一天服务器端的资源还是有可能会被耗尽}
舱壁模式(线程隔离)
- 限定每个业务能使用的线程数(说白了就是给每个业务都分配一个独立的线程池),这个时候每个业务能够使用的线程资源是有限的(同时也限制了每个业务请求处理的并发量),这样就可以避免耗尽整个Tomcat的资源(因为一个业务一旦出现故障,它最多是把整个线程池内的资源耗尽,而不会导致整个Tomcat的资源被耗尽),因此也叫线程隔离。?
- 这种模式它确实解决了雪崩问题,但是从资源上来讲会造成一定的浪费,比如服务提供者真的宕机了,但服务消费者每次还来去请求访问它,明明知道它挂了,还要去尝试访问,而且还要占用我一定的线程数,这显然是一种浪费。
?
断路器模式或熔断降级(模式):比较推荐的一种解决方案
- 由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,会认为该服务由导致雪崩的风险,会拦截访问该业务的一切请求,形成熔断,类似于快速失败机制,资源快速释放,从而避免雪崩问题的发生,该模式不会存在资源浪费的情况,因为如果知道服务出现故障了,就不让请求再去访问该服务了? =>? 类似于电路里面的保险丝儿。? ?
- 当检测到服务恢复正常响应以后,我们再去放行访问该业务的请求。?
- 熔断降级模式是解决雪崩问题里面比较好的一种方案。
?
如何避免因瞬间高并发流量而导致的服务故障??
限流 - 流量控制:
- 限制业务访问的QPS(每秒查询率,每秒的响应请求数,每秒钟处理请求的数量),避免服务因流量的突增而故障,?避免因为突发流量而导致的服务宕机。
- 使用Sentinel实现限流:Sentinel它可以按照服务所能够承受的一个频率去释放请求,把雪崩问题扼杀在了摇篮当中。总结:流量控制是预防雪崩,避免出现雪崩问题!
思考:那我就只用流量控制不就可以从根源上避免出现雪崩问题了吗?其它三种我不用不就行了。。。?
- 因为高并发引起的服务故障只是故障的原因之一,往往服务还会因为其它问题而出现故障,比如因为网络问题或者是Full GC引起的假死问题,这些问题都会引起服务故障,这个时候就要用到其它三种解决方案了。?
总结:
- 限流是对服务的保护,避免因突增的高并发流量而导致服务故障,进而避免雪崩,是一种预防措施。
- 而超时处理、线程隔离(舱壁模式)、熔断降级(断路器模式)是在部分服务故障时,将故障控制在一定范围,避免雪崩,是一种补救措施。?
1.2.服务保护框架或技术对比
在SpringCloud当中支持多种服务保护技术:
Hystrix和Sentinel都是非常成熟可靠的服务保护工具,早期比较流行的是Hystrix框架,但目前国内使用最广泛的还是阿里巴巴的Sentinel服务保护框架(是Spring Cloud Alibaba的组件之一),这里我们做下对比:?
关于Hystrix和Sentinel的对比,在Sentinel的官网上有一篇文章写的很详细:?
sentinel-vs-hystrix | Sentinel?
- Hystrix是Netflix开源的项目,而Sentinel是阿里巴巴开源的项目;
- Hystrix主要
- Sentinel底层是基于信号量来实现资源隔离,而Hystrix支持线程池隔离和信号量隔离,但默认情况下都是使用线程池隔离来实现资源隔离。
- 线程池隔离:在一个业务请求进入Tomcat以后,它会给每一个被隔离的业务创建一个独立的线程池。
- 信号量隔离:当业务请求进入Tomcat以后,
- Hystrix主要通过断路器来实现熔断保护,而Sentinel则提供了更灵活的流量控制、熔断、降级等策略。
- Hystrix主要提供了服务降级、服务熔断、线程隔离等功能,而Sentinel除了提供上述功能之外,还提供了实时监控、流量控制、热点参数限流、系统负载保护等功能。
- Hystrix适用于Java语言的微服务架构,而Sentinel则支持多种语言和多种类型的应用架构
- Hystrix已经停止维护,Spring Cloud在已经发布的项目中已经移除了对Hystrix的支持,而Sentinel在阿里巴巴内部广泛使用,并且有着活跃的社区支持。
? ? ? ???
Sentinel | Hystrix |
隔离策略 | 信号量隔离 | 线程池隔离/信号量隔离 |
熔断降级策略 | 基于慢调用比例或异常比例 | 基于失败比率 |
实时指标实现 | 滑动窗口 | 滑动窗口(基于 RxJava) |
规则配置 | 支持多种数据源 | 支持多种数据源 |
扩展性 | 多个扩展点 | 插件的形式 |
基于注解的支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 |
流量整形 | 支持慢启动、匀速排队模式 | 不支持 |
系统自适应保护 | 支持 | 不支持 |
控制台 | 开箱即用,可配置规则、查看秒级监控、机器发现等 | 不完善 |
常见框架的适配 | Servlet、Spring Cloud、Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |
?