此文章主要讲解 springcloud 中的服务熔断 Hystrix 的替换方案 Sentinel 的相关知识。
服务熔断 Hystrix 的替换方案 Sentinel
概述
- 2018 年底 Netflix 公司宣布 Hystrix 已经足够稳定,不再积极开发 Hystrix,该项目处于维护模式。就目前来看 Hystrix 是比较稳定的,并且 Hystrix 只是停止开发新的版本,并不是完全停止维护,Bug 什么的依然会维护。因此,短期内,Hystrix 依然是能继续使用的。但是从长远看,Hystrix 总会达到它的生命周期,那么 Spring Cloud 生态中是否有替代产品呢?
替换方案介绍
Alibaba Sentinel
- Sentinel 是阿里开源的一款熔断器的实现,目前在 Spring Cloud 的孵化器项目 Spring Cloud Alibaba 中的一员 Sentinel 本身在阿里内部已经被大规模采用,非常稳定。因此,可以作为一个很好的替代品。
Resilience4J
- Resilience4J 是一款轻量、简单,并且文档非常清晰、丰富的熔断工具,这也是 Hystrix 官方推荐的替代产品。不仅如此,Resilience4J 还原生支持 SpringBoot 1.x/2.x,而且监控也不像 Hystrix 一样弄 Dashboard/Hystrix 等一堆轮子,而是支持和 micrometer、prometheus 以及 Dropwizard metrics 进行整合。
Sentinel 概述
Sentinel 官网
Sentinel 是什么
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
- 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
去哪里下
- 下载地址。
能干嘛
安装和运行 Sentinel Dashboard
Sentinel 的组成
Sentinel 的组成可以分为两个部分:
核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持(见 主流框架适配 )。
控制台(Dashboard):控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。
安装和运行步骤
下载。
运行命令:
1 | # 直接启动 |
- Sentinel 的登录界面(访问地址默认是 http://localhost:8080/ ,用户名和密码为 sentinel/sentinel):
初始化演示工程
启动 Nacos 服务注册中心和配置中心
1 | startup.cmd -m standalone # 单机启动 |
搭建工程
新建模块
cloudalibaba-sentinel-service8401
POM 文件
1 |
|
YML 文件
1 | server: |
主启动类
1 |
|
业务逻辑
1 |
|
启动 8401。
流控规则
基本介绍
资源名:
唯一名称,默认请求路径。针对来源:
Sentinel 可以针对调用者进行限流,填写微服务名,默认 default(不区分来源)。阈值类型/单机阈值:
QPS(每秒请求数量):
当调用该 API 的 QPS 达到阈值的时候,进行限流。
线程数:
当调用该 API 的线程数达到阈值的时候,进行限流。
是否集群:
不需要集群。流控模式:
直接:
API 达到限流条件时,直接限流。
关联:
当关联的资源达到阈值的时候,就限流自己。
链路:
只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)[API 级别的针对来源]。
流控效果:
快速失败:
直接失败,抛异常。
Warm Up:
根据 codeFactor(冷加载因子,默认为 3)的值,从阈值/codeFactor,经过预热时长,才达到设置的 QPS 阈值。
排队等待:
匀速排队,让请求以匀速的速度通过,阈值类型必须设置为 QPS,否则无效。
流控模式之直接(默认直接–>快速失败)
配置说明
表示1秒内查询1次就是OK,如果超过1次,就直接–>快速失败,报默认错误。
测试
快速点击 http://localhost:8401/testA 。
结果显示:
流控模式之关联
是什么?
当和 A 关联的资源 B 达到阈值的时候,就限流 A 自己。
比如:电商系统中,下订单后面的流程就是支付,一旦支付超过阈值,就需要限制下订单。
配置说明
当关联资源/testB的QPS的阈值超过1的时候,就限流A的访问。
测试
通过 Postman 并发访问 http://localhost:8401/testB ,然后通过浏览器访问 http://localhost:8401/testA 。B 的并发访问,导致 A 挂了。
流控模式之链路
配置说明
- 多个请求调用 http://localhost:8401/testA ,如果 1 秒内请求次数超过 1 次,就会触发限流。
流控效果之预热
概述
Warm Up(
RuleConstant.CONTROL_BEHAVIOR_WARM_UP
)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过”冷启动”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。详细文档可以参考 流量控制 - Warm Up 文档,具体的例子可以参见 WarmUpFlowDemo。公式:阈值除以 coldFactor(冷加载因子,默认为 3),经过预热时长后才会达到阈值。
配置说明
系统初始化的的阈值是10/3约等于3,即阈值开始为3;经过5秒后阈值才慢慢升高恢复到10。
,即允许有缓冲的场景。
如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。
流控效果之排队等待
概述
配置说明
- http://localhost:8401/testA 每秒 1 次请求,超过的话就排队等待,等待的超时时间为 20000 毫秒。
降级规则
基本介绍
- 除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
- 现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的
弱依赖服务调用
进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。
降级规则之 RT
概述
平均响应时间超出阈值
且在时间窗口内通过的请求>=5
,两个条件同时满足后触发降级窗口期过后关闭断路器
RT 最大 4900 (更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX 才能生效)
代码
1 |
|
配置
测试
- 按照上述配置,永远是 1 秒钟 10 个进程调用了 testD,但是我们希望 200ms 内处理完本地任务,所以一直处于熔断状态,在未来 1 秒钟的时间窗口内,断路器打开(保险丝跳闸),微服务不可用。后续停止 jemter,没有那么大的访问量了,断路器关闭(保险丝恢复),微服务恢复 OK。
降级规则之异常比例
概述
- 异常比例 (
ERROR_RATIO
):当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是[0.0, 1.0]
,代表 0% - 100%。
代码
1 | "/testD") (value = |
配置
当单位统计时长内请求数量大于最小请求数目 5,并且异常比例大于阈值(0.2),则接下来的熔断时间内请求自动会被熔断。经过时间窗口时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
按照上述配置,单独访问一次,必然访问一次,报错一次,因为没有达到服务熔断的要求。开启 Jmeter 后,直接高并发发送请求,多次调用达到我们的配置条件了,断路器开启,微服务不可用了,不再报错而是服务降级了。
降级规则之异常数
概述
当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
配置
第一次访问: http://localhost:8401/testD 肯定报错,因为除数不能为 0,但是达到 5 次报错后,进入熔断后降级。
热点 key 限流
基本介绍
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制。
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制。
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
- Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。
@SentinelResource 注解
熔断降级方法分为系统默认和用户自定义两种,
@SentinelResource 注解和 Hystrix的@HystrixCommand 注解类似
,都是用来配置用户自定义的熔断降级方法。@SentinelResource 注解和@HystrixCommand 不同的是,
只处理Sentinel控制台配置的违规情况,并不处理异常
应用示例
代码
1 | "/testHotKey") (value = |
配置
访问: http://localhost:8401/testHotKey?p1=aaa ,当访问频率超出阈值,则进行限流。
如果 testHotKey 的参数 p1 的值不是 5,那么 QPS 是 1;如果参数 p1 的值是 5,那么 QPS 是 2000。
测试
测试 http://localhost:8401/testHotKey?p1=1 请求,如果每秒请求 1 次,不会熔断降级,如果每次请求超过 1 次,会触发熔断降级。
测试 http://localhost:8401/testHotKey?p1=5 请求,只要每秒请求不超过 2000 次,就不会熔断降级。
系统规则
基本介绍
- Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
背景
在开始之前,我们先了解一下系统保护的目的:
- 保证系统不被拖垮
- 在系统稳定的前提下,保持系统的吞吐量
长期以来,系统保护的思路是根据硬指标,即系统的负载 (load1) 来做系统过载保护。当系统负载高于某个阈值,就禁止或者减少流量的进入;当 load 开始好转,则恢复流量的进入。这个思路给我们带来了不可避免的两个问题:
- load 是一个“结果”,如果根据 load 的情况来调节流量的通过率,那么就始终有延迟性。也就意味着通过率的任何调整,都会过一段时间才能看到效果。当前通过率是使 load 恶化的一个动作,那么也至少要过 1 秒之后才能观测到;同理,如果当前通过率调整是让 load 好转的一个动作,也需要 1 秒之后才能继续调整,这样就浪费了系统的处理能力。所以我们看到的曲线,总是会有抖动。
- 恢复慢。想象一下这样的一个场景(真实),出现了这样一个问题,下游应用不可靠,导致应用 RT 很高,从而 load 到了一个很高的点。过了一段时间之后下游应用恢复了,应用 RT 也相应减少。这个时候,其实应该大幅度增大流量的通过率;但是由于这个时候 load 仍然很高,通过率的恢复仍然不高。
TCP BBR 的思想给了我们一个很大的启发。我们应该根据系统能够处理的请求,和允许进来的请求,来做平衡,而不是根据一个间接的指标(系统 load)来做限流。最终我们追求的目标是
在系统不被拖垮的情况下,提高系统的吞吐率,而不是 load 一定要到低于某个阈值
。如果我们还是按照固有的思维,超过特定的 load 就禁止流量进入,系统 load 恢复就放开流量,这样做的结果是无论我们怎么调参数,调比例,都是按照果来调节因,都无法取得良好的效果。Sentinel 在系统自适应保护的做法是,用 load1 作为启动自适应保护的因子,而允许通过的流量由处理请求的能力,即请求的响应时间以及当前系统正在处理的请求速率来决定。
系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且
仅对入口流量生效
。入口流量指的是进入应用的流量(EntryType.IN
),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。系统规则支持以下的模式:
Load 自适应
(仅对 Linux/Unix-like 机器生效
):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的maxQps * minRt
估算得出。设定参考值一般是CPU cores * 2.5
。
CPU usage
(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
平均 RT
:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
并发线程数
:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS
:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
系统规则配置界面
@SentinelResource 讲解
修改模块
cloudalibaba-sentinel-service8401
新增 Controller
1 |
|
很明显,上面虽然自定义了兜底方法,但是耦合度太高,下面要解决这个问题。
自定义全局 BlockHandler 处理类
写一个 CustomerBlockHandler 自定义限流处理类:
Sentinel 整合 Ribbon 系列
准备工作
- 需要启动 Nacos 和 Sentinel。
服务提供者
新建模块
cloudalibaba-provider-payment9003
cloudalibaba-provider-payment9004
POM 文件
1 | <dependencies> |
YML 文件
注意改端口号就行
1 | server: |
主启动类
编写主启动类。
业务类
1 |
|
服务消费者
新建模块
cloudalibaba-consumer-nacos-order84
POM 文件
1 | <dependencies> |
yaml 文件
1 | server: |
主启动类
略
业务类
配置类
1 |
|
Controller
1 |
|
上面只实现了 以 nacos 作为服务注册中心,消费者使用 ribbon 实现负载均衡调用提供者的效果。
进行相关配置
在消费者中操作
只配置 fallback
1 | "/consutomer/fallback/{id}") ( |
业务异常
会被 fallback 处理,返回我们自定义的提示信息,而如果给它加上流控,并触发阈值,只能返回sentinel默认的提示信息
。
只配置 blockHandler
1 | "/consutomer/fallback/{id}") ( |
这时候的效果就是,运行异常直接报错错误页面。在 sentinel 上添加一个降级规则,设置 2s 内触发异常 2 次,触发阈值以后,返回的是我们自定义的 blockhanlder 方法返回的内容。
两者都配置
1 | "/consutomer/fallback/{id}") ( |
明显两者都是有效的,可以同时配置。
若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。
异常忽略
抛出某异常时,不需要进行兜底处理。
Sentinel 整合 Feign 系列
修改 84 模块
84 消费者调用提供者 9003
Feign组件一般是消费侧
POM 文件
1 | <dependency> |
YML 文件
1 | # 激活Sentinel对Feign的支持 |
主启动类
添加注解 :@EnableFeignClients
激活 open-feign
Service 接口
1 | "nacos-payment-provider", fallback = PaymentFallbackService.class) // 实现降级 (value = |
Service 接口实现类实现降级
1 | // 不要忘记 |
Controller
1 |
|
测试
启动相关组件和微服务。
正常访问。
测试,关闭提供者9003微服务,会触发自动降级,不会被耗死。
Sentinel 规则持久化
是什么?
- 一旦我们重启应用,Sentinel 规则将消失,生产环境需要将配置规则进行持久化。
怎么玩?
- 将 Sentinel 中的规则持久化到 Nacos 保存,只要 Nacos 里面的配置不删除,那么 Sentinel 中的规则将持续有效。
步骤(修改服务消费者)
POM 文件
1 | <dependency> |
YML 文件
1 | server: |
在 Nacos 中添加业务规则配置
去 nacos 上创建一个 dataid ,名字和 yml 配置的一致,比如我这里是 nacos-order-consumer ,json 格式,内容如下
1 | [ |
1 | resource:# 资源名称。 |
启动应用,然后刷新 Sentinel,发现存在 关于 /testA 请求路径的流控规则。
停止 8401 在看 sentinel,发现里面没有内容,当多次调用接口,关于接口的流控规则又出现了,持久化验证成功。
发布时间: 2021-01-22
最后更新: 2024-06-24
本文标题: SpringCloud Alibaba入门到精通(十五)- 服务熔断Hystrix的替换方案Sentinel
本文链接: https://blog-yilia.xiaojingge.com/posts/727976ee.html
版权声明: 本作品采用 CC BY-NC-SA 4.0 许可协议进行许可。转载请注明出处!
