Sentinel详解【流控、降级、热点、授权】
一、Docker
1、docker-compose
sentinel:
image: bladex/sentinel-dashboard
container_name: sentinel-dashboard
restart: always
environment:
JAVA_OPTS: "-Dserver.port=8858 -Dcsp.sentinel.dashboard.server=localhost:8858 -Dproject.name=sentinel-dashboard"
ports:
- "8858:8858"
volumes:
- /var/docker/server/sentinel/logs:/root/logs
http://192.168.52.10:8858
二、Java
1. pom
<!-- 调用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
<!-- sentinel 的数据持久化 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.6</version>
</dependency>
2、yml
spring:
cloud:
#流控、降级、热点、DashBoard及设置
sentinel:
transport:
# 添加sentinel的控制台地址
dashboard: 192.168.52.10:8858
# 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
port: 8858
# 默认将调用链路收敛,需要打开才可以进行链路流控
web-context-unify: false
filter:
# 默认收敛所有URL的入口Context,因此链路限流此时不生效,若使用链路流控模式则设置为false
enabled: true
三、Sentinel几种控制方式
(一)流控:流量控制
1、QPS+直接+快速失败
/trading/add 接口每秒内只能通过1个请求,其他请求会被限流,报错429
2. 线程数+直接+快速失败
针对并发,/trading/add 同时只能有1个线程执行,若有两个线程同时访问,则其中1个请求会被限流,报错429
3. QOS+关联+快速失败
当 /trading/add 接口 同时有1个以上线程访问时,则对 /trading/getPageList 接口进行限流,但不会对/trading/add进行限流。
场景:下单和支付接口进行关联。如若支付接口达到阈值,就限定下单接口少产生支付接口,缓解压力!
4. QOS+链路+快速失败
当在 /trading/add 接口中访问 goods 普通方法时,1秒QPS达到2个及以上,则对 /trading/add 接口进行限流,但不对影响其它接口访问 goods 方法
//在普通方法goods上加注解 @SentinelResource("goods")
5. 流控效果
5.1 快速失败
达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。
5.2 Warm Up
预热模式,是应对服务冷启动的一种方案。适用于突然增大的流量转化为缓步增长。阈值一般是一个微服务能承担的最大QPS,但是一个服务刚刚启动时,一切资源尚未初始化(冷启动),如果直接将QPS跑到最大值,可能导致服务瞬间宕机。
请求阈值初始值是 maxThreshold / coldFactor,持续指定时长后,逐渐提高到maxThreshold值。而coldFactor的默认值是3
例如,我设置QPS的阈值为10,预热时间为5秒,那么初始阈值就是 10 / 3 ,也就是3,然后在5秒后逐渐增长到10
5.3 排队等待
让请求以均匀的速率通过,单机阈值为每秒通过的请求数,其余的排队等待;其次,还可以设置一个排队等待的超时时间,若请求在超时时间内还未被处理,则会被丢弃。
(二)热点限流
统计请求参数值相同的请求,判断统计时长内是否超过QPS阈值。比如在并发请求 /trading/info 接口中判断相同参数的QOS不能超过某个阀值
//在请求接口Controller /info/{id}上加注解: @SentinelResource(value = "hot", blockHandler = "fallback_hostkey") //并定义如下限流返回方法 public String fallback_hostkey(String p1, String p2, BlockException blockException){ return "限流咯。。。。"; }
(三)降级熔断
熔断建议设置监控接口里的Feign远程调用,因为一旦发生熔断和隔离是不允许外界访问该接口。监控远程调用是因为远程调用使用的feign-api模块对远程调用接口方法写了发生熔断和隔离时返回空对象。如果监控外部接口,一旦发生熔断则直接报错,阻止用户访问接口并不会返回空对象(因为该接口方法没写发生熔断和隔离时返回空对象)。
1、慢调用比例
当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx 来配置。
2、异常比例
当资源的每秒请求量 >= N(可配置),并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
3、异常数
当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
(四)授权
授权规则可以对请求方来源做判断和控制。(通过判断请求方的请求头是否携带指定的参数来判断)
1. sentinel授权介绍
授权规则可以对调用方的来源做控制,有白名单和黑名单两种方式。
白名单:来源(origin)在白名单内的调用者允许访问
黑名单:来源(origin)在黑名单内的调用者不允许访问
点击左侧菜单的授权,可以看到授权规则:
资源名:就是受保护的资源,例如/order/
流控应用:是来源者的名单,
如果是勾选白名单,则名单中的来源被许可访问。
如果是勾选黑名单,则名单中的来源被禁止访问。
比如:
我们允许请求从gateway到order-service,不允许浏览器访问order-service,那么白名单中就要填写网关的来源名称(origin)。
如何得到origin呢?Sentinel是通过RequestOriginParser这个接口的parseOrigin来获取请求的来源的
public interface RequestOriginParser { /** * 从请求request对象中获取origin,获取方式自定义 */ String parseOrigin(HttpServletRequest request); }
这个方法的作用就是从request对象中,获取请求者的origin值并返回。
默认情况下,sentinel不管请求者从哪里来,返回值永远是default,也就是说一切请求的来源都被认为是一样的值default。
因此,我们需要自定义这个接口的实现,让不同的请求,返回不同的origin。
2. sentinel设置授权
2.1 给网关添加请求头
既然获取请求origin的方式是从reques-header中获取origin值,我们必须让所有从gateway路由到微服务的请求都带上origin头。
这个需要利用之前学习的一个GatewayFilter来实现,AddRequestHeaderGatewayFilter。
修改gateway服务中的application.yml,添加一个defaultFilter:
spring: cloud: gateway: default-filters: - AddRequestHeader=origin,gateway #逗号前是key,后面是value routes: # ...略
这样,从gateway路由的所有请求都会带上origin头,值为gateway。而从其它地方到达微服务的请求则没有这个头。
2.2 获取请求的origin
例如order-service服务中,我们定义一个RequestOriginParser的实现类:我们会尝试从request-header中获取origin值。
@Component public class HeaderOriginParser implements RequestOriginParser { @Override public String parseOrigin(HttpServletRequest request) { // 1.获取请求头 String origin = request.getHeader("origin"); // 2.非空判断 if (StringUtils.isEmpty(origin)) { origin = "blank"; } return origin; } }
2.3 sentinel操作
我们添加一个授权规则,放行origin值为gateway的请求。配置如下:
现在,我们直接跳过网关,访问order-service服务:
通过网关访问:
四、系统自适应限流
之前的配置操作,采取的是针对单个请求地址、请求别名进行配置的限流操作,sentinel同时也提供了一种很潮流的方式实现配置操作—系统自适应限流。
系统规则中的系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
Load 自适应(仅支持Linux/Unix-like)
系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。(系统核心数*2.5)
CPU usage(1.5.0+ 版本)
当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
平均 RT
当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
并发线程数
当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS
当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
五、自定义异常
默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。异常结果都是flow limmiting(限流)。这样不够友好,无法得知是限流还是降级还是授权拦截。
@Component public class SentinelExceptionHandler implements BlockExceptionHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception { String msg = "未知异常"; int status = 429; if (e instanceof FlowException) { msg = "请求被限流了"; } else if (e instanceof ParamFlowException) { msg = "请求被热点参数限流"; } else if (e instanceof DegradeException) { msg = "请求被降级了"; } else if (e instanceof AuthorityException) { msg = "没有权限访问"; status = 401; } response.setContentType("application/json;charset=utf-8"); response.setStatus(status); response.getWriter().println("{\"msg\": " + msg + ", \"status\": " + status + "}"); } }
六、规则持久化
sentinel的所有规则都是内存存储,重启后所有规则都会丢失。在生产环境下,我们必须确保这些规则的持久化,避免丢失。
1、规则管理模式
规则是否能持久化,取决于规则管理模式,sentinel支持三种规则管理模式:
- 原始模式:Sentinel的默认模式,将规则保存在内存,重启服务会丢失。
- pull模式(存储各服务器本地,一定时间内会轮询检查规则并更新)
- push模式(存储在nacos注册中心)【推荐】
2. pull模式
pull模式:控制台将配置的规则推送到Sentinel客户端,而客户端会将配置规则保存在本地文件或数据库中。以后会定时去本地文件或数据库中查询,更新本地规则。
3. push模式
push模式:控制台将配置规则推送到远程配置中心,例如Nacos。Sentinel客户端监听Nacos,获取配置变更的推送消息,完成本地配置更新。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了