Alibaba流控组件Sentinel实战
2025-02-26 15:01:14 0 举报
AI智能生成
Alibaba流控组件Sentinel实战,分享给大家学习。 更多干货内容,欢迎关注我的公众号:Fox爱分享
作者其他创作
大纲/内容
课程目标
理解常用的服务雪崩解决方案
掌握sentinel的使用,掌握sentinel控制台常用的规则配置
理解sentinel的工作原理
理解Sentinel规则生效流程,能自己实现sentinel配置规则的持久化
怎么学
没接触过微服务的同学一定要先把《轻松玩转微服务:新手入门Spring Cloud Alibaba》这节课跟一遍
课上代码
项目地址
git切换到fox-dev分支,选择 tag v2.4.0,v2.4.1
高频面试题:服务雪崩及其解决方案
需求
当服务访问量达到一定程度,流量扛不住的时候,该如何处理?
服务之间相互依赖,当服务A出现响应时间过长,影响到服务B的响应,进而产生连锁反应,直至影响整个依赖链上的所有服务,该如何处理?
商品详情展示服务会依赖商品服务, 价格服务, 商品评论服务。调用三个依赖服务会共享商品详情服务的线程池
如果其中的商品评论服务不可用, 就会出现线程池里所有线程都因等待响应而被阻塞, 从而造成服务雪崩
什么是服务雪崩
在微服务调用链路中,因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就叫服务雪崩效应。
当服务调用者使用同步调用时, 会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 于是服务雪崩效应产生了。
常见解决雪崩问题的方案
超时机制
设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止地等待。
由于释放资源速度较快,一定程度上可以抑制资源耗尽的问题。但是这种解决方案只是缓解了雪崩问题,并不能解决雪崩问题。
服务限流
限制业务访问的QPS,避免服务因为流量的突增而故障。
这种是从预防层面来解决雪崩问题。
资源隔离
资源隔离分为进程隔离,线程隔离和信号量隔离。
隔离机制的本质就是将服务调用的粒度划分的更小,以此来减少服务生产崩溃而对服务调用带来的影响,避免服务雪崩现象产生。
比如限定每个业务能使用的线程数,避免耗尽整个线程池的资源。当商品评论服务不可用时, 即使商品服务独立分配的20个线程全部处于同步等待状态,也不会影响其他依赖服务的调用。
服务熔断降级
参考了电路熔断的设计
如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
当依赖的服务有大量超时时,在让新的请求去访问根本没有意义,只会无畏的消耗现有资源。
有服务熔断,必然要有服务降级。
所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。 例如:(备用接口/缓存/mock数据) 。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。
Sentinel基础使用详解
为什么会用到sentinel
为了提高系统运行期间的稳定性和可用性
sentinel是什么
Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件
官方文档
怎么用
sentinel的核心概念
资源(Resource)
规则(Rule)
Sentinel快速开始
基于API实现资源保护
1)引入依赖
2)定义受保护的资源和流控规则
测试效果:http://localhost:8800/hello
缺点
业务侵入性很强,需要在controller中写入非业务代码.
配置不灵活, 添加新的受保护资源,需要手动添加 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控制台
java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=tlmall-sentinel-dashboard:8888 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar
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注解
异常处理配置
源码跟踪:
com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor
com.alibaba.cloud.sentinel.custom.SentinelProtectInterceptor#intercept
com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor
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 组件。
源码跟踪: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:资源名,即限流规则的作用对象
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")注解,否则不生效
2.参数必须是7种基本数据类型才会生效
2.参数必须是7种基本数据类型才会生效
启动订单服务tlmall-order-sentinel-demo,测试
查询订单接口
配置热点规则
注意: 资源名必须是@SentinelResource(value="资源名")中 配置的资源名,热点规则依赖于注解
测试
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。
CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。
RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
启动订单服务tlmall-order-sentinel-demo,测试
配置系统规则
为了演示出效果,这里使用压测工具jmeter进行测试
线程组的配置
测试订单接口
查看实时监控,可以看到限流效果
授权控制规则
官方文档
来源访问控制(黑白名单)
来源访问控制根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
来源访问控制规则(AuthorityRule)配置项:
- resource:资源名,即限流规则的作用对象。
- 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规则持久化源码分析图

收藏

收藏
0 条评论
下一页