Alibaba流控组件Sentinel实战
2025-02-26 15:01:14 0 举报仅支持查看
AI智能生成
Alibaba流控组件Sentinel实战,分享给大家学习。 更多干货内容,欢迎关注我的公众号:Fox爱分享
Sentinel
sentinel持久化
流控降级
微服务
SpringCloudAlibaba
模版推荐
作者其他创作
大纲/内容
课程目标
理解常用的服务雪崩解决方案
掌握sentinel的使用,掌握sentinel控制台常用的规则配置
理解sentinel的工作原理
理解Sentinel规则生效流程,能自己实现sentinel配置规则的持久化
怎么学
没接触过微服务的同学一定要先把《轻松玩转微服务:新手入门Spring Cloud Alibaba》这节课跟一遍
课上代码
项目地址
git切换到fox-dev分支,选择 tag v2.4.0,v2.4.1
高频面试题:服务雪崩及其解决方案
需求
当服务访问量达到一定程度,流量扛不住的时候,该如何处理?<br>
服务之间相互依赖,当服务A出现响应时间过长,影响到服务B的响应,进而产生连锁反应,直至影响整个依赖链上的所有服务,该如何处理?
商品详情展示服务会依赖商品服务, 价格服务, 商品评论服务。调用三个依赖服务会共享商品详情服务的线程池
如果其中的商品评论服务不可用, 就会出现线程池里所有线程都因等待响应而被阻塞, 从而造成服务雪崩
什么是服务雪崩
在微服务调用链路中,因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就叫服务雪崩效应。
当服务调用者使用同步调用时, 会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 于是服务雪崩效应产生了。
常见解决雪崩问题的方案
超时机制
设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止地等待。
由于释放资源速度较快,一定程度上可以抑制资源耗尽的问题。但是这种解决方案只是缓解了雪崩问题,并不能解决雪崩问题。
服务限流
限制业务访问的QPS,避免服务因为流量的突增而故障。
这种是从预防层面来解决雪崩问题。
资源隔离
资源隔离分为进程隔离,线程隔离和信号量隔离。
隔离机制的本质就是将服务调用的粒度划分的更小,以此来减少服务生产崩溃而对服务调用带来的影响,避免服务雪崩现象产生。
比如限定每个业务能使用的线程数,避免耗尽整个线程池的资源。当商品评论服务不可用时, 即使商品服务独立分配的20个线程全部处于同步等待状态,也不会影响其他依赖服务的调用。
服务熔断降级
参考了电路熔断的设计
如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
当依赖的服务有大量超时时,在让新的请求去访问根本没有意义,只会无畏的消耗现有资源。
有服务熔断,必然要有服务降级。
所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。 例如:(备用接口/缓存/mock数据) 。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。
Sentinel基础使用详解
为什么会用到sentinel
为了提高系统运行期间的稳定性和可用性
sentinel是什么
Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件
官方文档
怎么用
sentinel的核心概念
资源(Resource)
规则(Rule)
Sentinel快速开始
基于API实现资源保护
1)引入依赖
2)定义受保护的资源和流控规则
测试效果:http://localhost:8800/hello
缺点
业务侵入性很强,需要在controller中写入非业务代码.<br>
配置不灵活, 添加新的受保护资源,需要手动添加 init方法来添加流控规则
基于@SentinelResource注解埋点实现资源保护
Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等。
注意:注解方式埋点不支持 private 方法。
源码入口:com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect
接入步骤
1)引入依赖
2)配置切面支持
3)HelloController中编写测试逻辑,添加@SentinelResource,并配置blockHandler和fallback
使用注意事项
单独新建一个类用于处理受保护资源的BlockException和fallback,更加的解耦且灵活。
可以通过配置blockHandlerClass和fallbackClass实现
测试效果:http://localhost:8800/hello2
微服务中如何使用sentinel
sentinel的安装
官方参考文档
sentinel由两部分构成
核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持
控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。
安装Sentinel控制台
注意版本
Sentinel Version: 1.8.6
官方文档地址
下载地址
https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar
启动sentinel控制台
<br>java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=tlmall-sentinel-dashboard:8888 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar
如若8080端口冲突,可使用 -Dserver.port=新端口 进行设置。
访问sentinel控制台
从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel
访问:http://localhost:8888
注意: Sentinel 会在客户端首次调用时候进行初始化,开始向控制台发送心跳包。因此需要确保客户端有访问量,才能在控制台上看到监控数据。
Java应用和Sentinel Dashboard通信原理
测试:http://localhost:8719/getRules?type=flow 获取流控规则信息
sentinel整合微服务
官方参考文档
以订单服务为例
1)引入sentinel的依赖
2)业务代码中配置需要保护的资源
mvc接口方法自动埋点,不需要配置
非mvc接口方法可以使用@SentinelResource 注解用来标识资源是否被限流、降级
3)添加yml配置,为订单服务设置sentinel控制台地址
测试,重启订单服务,对获取订单接口进行流控
启动sentinel控制台,在sentinel控制台中设置流控规则
注意:需要先访问一次获取接口,sentinel控制台才会有订单服务记录
将单机阈值调为1,用postman测试获取接口,是否被流控
通过Sentinel 对外暴露的 Endpoint查看流控配置
1)引入依赖
2)添加Sentinel后,需要暴露/actuator/sentinel端点
3)访问http://localhost:8060/actuator/sentinel, 可以查看流控规则信息
RestTemplate整合Sentinel
Spring Cloud Alibaba Sentinel 支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,在构造 RestTemplate bean的时候需要加上 @SentinelRestTemplate 注解。
Sentinel RestTemplate 限流的资源规则提供两种粒度:
- httpmethod:schema://host:port:协议、主机和端口
- httpmethod:schema://host:port/path:协议、主机、端口和路径
整合步骤
以tlmall-user-sentinel-demo为例,会员服务查询订单服务,已经接入sentinel
1)RestTemplate添加@SentinelRestTemplate注解
异常处理配置
源码跟踪:<br>com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor<br>com.alibaba.cloud.sentinel.custom.SentinelProtectInterceptor#intercept
2)添加yml配置,开启sentinel对resttemplate的支持,默认开启,可忽略
3) 测试
在sentinel控制台中对被保护的restTemplate资源进行限流配置,测试是否限流
访问订单接口localhost:8050/user/getOrder?userId=fox
在sentinel控制台中对被保护的restTemplate资源进行熔断规则配置,测试是否熔断降级
访问订单接口http://localhost:8050/user/getOrder?userId=foxxxx
注意:要先删除限流规则,再测试
OpenFeign整合Sentinel
Sentinel 适配了 Feign 组件。<br>
源码跟踪:com.alibaba.cloud.sentinel.feign.SentinelInvocationHandler#invoke
整合步骤
1)yml配置文件中开启 Sentinel 对 Feign 的支持
2)在Feign的声明式接口上添加fallback或者fallbackFactory属性
3)测试
访问:http://localhost:8050/user/getOrder?userId=fox,生成如下sentinel openFeign的资源
测试限流
在sentinel控制台配置流控规则
访问:http://localhost:8050/user/getOrder?userId=fox,测试流控规则是否生效
测试降级
访问http://localhost:8050/user/getOrder?userId=foxxxx(userId=foxxxx订单服务会抛出异常),测试降级是否生效
关闭tlmall-order-sentinel-demo服务,访问http://localhost:8050/user/getOrder?userId=fox,测试降级是否生效
Sentinel工作原理
官方文档
Sentinel常用规则配置详解
通过Sentinel控制台进行sentinel的规则配置
Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。
阿里云提供了 企业级的 Sentinel 控制台,应用高可用服务 AHAS
测试环境准备
启动nacos server
启动sentinel 控制台
演示环境初始代码
git切换到fox-dev分支,选择 tag v2.4.0
结合课上演示掌握sentinel开源控制台的规则配置
实时监控
监控接口的通过的QPS和拒绝的QPS
注意:请确保 Sentinel 控制台所在的机器时间与自己应用的机器时间保持一致,否则会导致拉不到实时的监控数据。
注意: 实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。
簇点链路
用来显示微服务的所监控的API。
注意: 簇点监控是内存态的信息,它仅展示启动后调用过的资源。
流控规则
官方文档
影响流控效果的关键因素
resource:资源名,即限流规则的作用对象<br>
count: 限流阈值
grade: 限流阈值类型,QPS 或线程数
strategy: 根据调用关系选择策略
基于 QPS/并发数的流量控制
QPS
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置流控规则
流控的效果
为什么是这个效果?
参考源码:DefaultBlockExceptionHandler
新的需求:需要对异常进行统一管理
实现思路
springwebmvc接口资源限流入口在HandlerInterceptor的实现类AbstractSentinelInterceptor的preHandle方法中,对异常的处理是BlockExceptionHandler的实现类
自定义BlockExceptionHandler 的实现类统一处理BlockException
重启服务后测试的流控效果
注意:因为流控规则是写入内存中的,重启服务流控规则会丢失,需要重新配置
并发线程数
并发线程数控制用于保护业务线程池不被慢调用耗尽。
简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置流控规则
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
流控效果
基于调用关系的流量控制
根据调用方限流
origin 参数标明了调用方身份。
可通过以下命令来展示不同的调用方对同一个资源的调用数据
资源/order/getOrder被两个不同的调用方调用
注意:默认是没有实现来源数据的,需要实现RequestOriginParser接口
简单理解就是:可以实现对userId=fox限流,对userId=foxx不限流
拓展: 可以实现对请求头,请求参数的流控
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置流控规则
自定义的RequestOriginParser接口实现类MyRequestOriginParser中指定了userId的值可以为来源
测试效果
http://localhost:8060/order/getOrder?userId=fox 会被流控
因为实现了MyRequestOriginParser,userId=fox会被解析出fox为来源赋值给origin,而来源fox是被流控了的
http://localhost:8060/order/getOrder?userId=foxx 不会被流控
具有关系的资源流量控制:关联流量控制
简单理解就是:当关联资源A达到阈值,对资源B流控
可使用关联限流来避免具有关联关系的资源之间过度的争抢,比如当写库操作过于频繁时(可以配置一个阈值),读数据的请求会被限流
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置流控规则
测试效果
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
指定http请求接口是 http://localhost:8060/order/getOrderById/1
http://localhost:8060/order/getOrder?userId=fox 会被流控
根据调用链路入口限流:链路限流
简单点理解就是: 资源A和B都会调用C,设置入口资源是A,当C达到阈值了,对入口资源A进行流控,而不会对B进行流控
注意,高版本此功能直接使用不生效,如何解决?
1.8.6中需要在yml中配置spring.cloud.sentinel.web-context-unify属性为false
启动订单服务tlmall-order-sentinel-demo,测试
准备测试环境
OrderServiceImpl#getOrderById 方法添加注解@SentinelResource进行资源保护
参考OrderController#getOrderById方法 新增TestController测试类
测试接口
配置流控规则
测试效果
http://localhost:8060/test2/1 会被流控
http://localhost:8060/test1/1 不会被流控
流控效果
快速失败(直接拒绝)
达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式。
用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。
Warm Up(预热)
预热模式,对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值。
冷加载因子: codeFactor 默认是3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置流控规则
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
流控效果
匀速排队(排队等待)
让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长
会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
主要用于处理间隔性突发的流量,例如消息队列。
注意:匀速排队模式暂时不支持 QPS > 1000 的场景。
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置流控规则
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
流控效果
熔断降级规则
官方文档
作用
对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。
熔断降级规则(DegradeRule)属性
熔断策略
慢调用比例
当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
启动订单服务tlmall-order-sentinel-demo,测试
准备测试环境
添加测试代码TestController#test
查询接口
配置降级规则
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
查看实时监控,可以看到断路器熔断效果
此时浏览器访问会出现服务降级结果
异常比例
当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
启动订单服务tlmall-order-sentinel-demo,测试
准备测试环境
添加测试代码TestController#test222
查询接口
配置降级规则
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
查看实时监控,可以看到断路器熔断效果
异常数
当单位统计时长内的异常数目超过阈值之后会自动进行熔断。
启动订单服务tlmall-order-sentinel-demo,测试
准备测试环境
添加测试代码TestController#test222
查询接口
配置降级规则
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
查看实时监控,可以看到断路器熔断效果
热点规则
官方文档
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。
注意
1.热点规则需要使用@SentinelResource("resourceName")注解,否则不生效<br>2.参数必须是7种基本数据类型才会生效
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置热点规则
注意: 资源名必须是@SentinelResource(value="资源名")中 配置的资源名,热点规则依赖于注解
测试<br>
http://localhost:8060/order/getOrderById/3 限流的阈值为1
http://localhost:8060/order/getOrderById/1 限流的阈值为2
系统规则
官方文档
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。
系统自适应保护的目的
- 保证系统不被拖垮
- 在系统稳定的前提下,保持系统的吞吐量
系统规则支持以下的阈值类型
Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。<br>
CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。<br>
RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。<br>
线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。<br>
入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
启动订单服务tlmall-order-sentinel-demo,测试
配置系统规则
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
测试订单接口
查看实时监控,可以看到限流效果
授权控制规则
官方文档
来源访问控制(黑白名单)
来源访问控制根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
来源访问控制规则(AuthorityRule)配置项:<br>
- resource:资源名,即限流规则的作用对象。<br>
- limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB。
- strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。
origin 参数标明了调用方身份。
其实和限流规则中的调用方限流本质的原理是一致的,只是应用场景的区别而已
可通过以下命令来展示不同的调用方对同一个资源的调用数据
资源/order/getOrder被两个不同的调用方调用
注意:默认是没有实现来源数据的,需要实现RequestOriginParser接口
简单理解就是:可以实现对userId的 黑白名单配置
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置授权规则
自定义的RequestOriginParser接口实现类MyRequestOriginParser中指定了userId的值可以为来源
测试效果
http://localhost:8060/order/getOrder?userId=fox 不会被限制访问
http://localhost:8060/order/getOrder?userId=foxx 会被限制访问
foxx是黑名单
集群规则
官网文档
开源版sentinel 控制台没有真正实现(不做过多讲解,了解即可)
云上版本 AHAS Sentinel 提供开箱即用的全自动托管集群流控能力,无需手动指定/分配 token server 以及管理连接状态,同时支持分钟小时级别流控、大流量低延时场景流控场景,同时支持 Istio/Envoy 场景的 Mesh 流控能力。
Sentinel规则持久化
Sentinel控制台规则推送三种模式
原始模式(默认)
如果不做任何修改,Dashboard 的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中
优点
简单,无依赖
缺点
应用重启规则就会消失,仅用于简单测试,不能用于生产环境
改造方式
扩展写数据源(WritableDataSource)
核心源码参考:com.alibaba.csp.sentinel.command.handler.ModifyRulesCommandHandler#handle
拉模式
客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等
优点
简单,无任何依赖;规则持久化
缺点
不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题。
改造方式
扩展写数据源(WritableDataSource)
官方实现的方案
基于文件实现拉模式
官方demo: sentinel-demo/sentinel-demo-dynamic-file-rule
fox老师实现的方案
基于Nacos实现拉模式,实现写数据源
当sentinel控制台推送规则到内存后就将规则发布到Nacos配置中心
核心实现:com.alibaba.nacos.api.config.ConfigService#publishConfig
推模式
规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。
生产环境下一般采用 push 模式的数据源。
优点
规则持久化;有更好的实时性和一致性保证
缺点
引入第三方依赖
改造方式
扩展读数据源(ReadableDataSource)
官方实现方案
基于Nacos配置中心控制台实现推送
官方demo: sentinel-demo-nacos-datasource
基于Nacos配置中心控制台实现推送
以tlmall-order-sentinel-demo为例,测试流控规则是否能持久化
实现步骤
1)引入依赖
此依赖包中实现了读数据源
2)yml中增加从Nacos数据源读取流控规则的配置
如何指定规则类型: RuleType
源码参考:com.alibaba.cloud.sentinel.datasource.config.AbstractDataSourceProperties#postRegister
3) nacos配置中心中配置流控规则
测试
重启订单微服务,测试流控规则是否生效
重启之后,订单微服务是存在流控规则的
从Nacos配置中心拉取到了流控规则
测试订单查询接口
订单查询接口被流控了
缺点
通过sentinel控制台修改的流控规则还是会丢失
发现问题
只能从Nacos配置中心读取规则数据,通过Sentinel控制台推送的规则不能写入Nacos配置中心,规则数据还是会丢失
新的需求
通过Sentinel控制台修改流控规则后,Nacos配置中心对应的流控规则也会更新
解决方案
方案1
改造Sentinel控制台,配置规则的时候推送到Nacos配置中心
不建议,需要改造Sentinel控制台源码
如何改造?后续sentinel持久化源码分析课中有实现
方案2
微服务端扩展写数据源(WritableDataSource),将规则保存到Nacos配置中心
思路: 推拉结合,使用官方提供的读数据源扩展,自己实现Nacos写数据源
参考课上源码实现
fox-dev分支 tag v2.4.2
测试
Sentinel控制台修改流控规则后,Nacos配置中心的流控规则是否也会被更新
Sentinel控制台流控规则阈值改为2
Nacos配置中心中流控规则阈值也变成了2
更多的原理和实现方式可以在后续源码课程中深入学习
Sentinel规则持久化进阶课程
Sentinel规则持久化拉模式实战及其源码分析(两节)
Sentinel规则持久化源码分析图
收藏
立即使用
收藏
立即使用
收藏
立即使用
收藏
立即使用
Collect
Get Started
Collect
Get Started
Collect
Get Started
Collect
Get Started
评论
0 条评论
下一页