前言
流量控制有以下几个角度:
- 资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
- 运行指标,例如 QPS、线程池、系统负载等;
- 控制的效果,例如直接限流、冷启动、排队等。
Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。
熔断降级
除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。这个问题和Hystrix里面描述的问题是一样的。
注:上面我使用的是 linux 启动 sentinel,但是下面为了操作方便均在 windows 上演示
为了使得客户端接入控制台,需要:
- 客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信。您可以通过
pom.xml引入 JAR 包
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-transport-simple-http</artifactId> <version>1.8.6</version> </dependency>
- 启动时加入 JVM 参数
-Dcsp.sentinel.dashboard.server=consoleIp:port指定控制台地址和端口 (前面已经指定)。更多的参数参见启动参数文档。
- 确保应用端有访问量
Sentinel 可以简单的分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。 使用 Sentinel 来进行熔断保护,主要分为几个步骤:
注:若您的应用为 Spring Boot 或 Spring Cloud 应用,您可以通过 Spring 配置文件来指定配置,详情请参考Spring Cloud Alibaba Sentinel 文档
定义资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,RPC 接口方法,甚至可以是一段代码。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
把需要控制流量的代码用 Sentinel的关键代码 SphU.entry(“资源名”) 和 entry.exit() 包围起来即可。
导入依赖
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2022.0.0.0</version> </dependency>
配置 application.yml
spring: cloud: sentinel: transport: dashboard: localhost:8849 #sentinel控制台的请求地址
@SentinelResource 注解
注意:注解方式埋点不支持 private 方法。
@SentinelResource用于定义资源,并提供可选的异常处理和 fallback 配置项。
@SentinelResource注解包含以下属性:
- value:资源名称,必需项(不能为空)
- entryType:entry 类型,可选项(默认为 EntryType.OUT)
- blockHandler / blockHandlerClass
定义规则
规则主要有流控规则、 熔断降级规则、系统规则、权限规则、热点参数规则等
硬编码方式定义系统规则
private void initSystemRule() { List<SystemRule> rules = new ArrayList<>(); SystemRule rule = new SystemRule(); rule.setHighestSystemLoad(10); rules.add(rule); SystemRuleManager.loadRules(rules); }
加载不同规则
FlowRuleManager.loadRules(List<FlowRule> rules); // 修改流控规则 DegradeRuleManager.loadRules(List<DegradeRule> rules); // 修改降级规则 SystemRuleManager.loadRules(List<SystemRule> rules); // 修改系统规则 AuthorityRuleManager.loadRules(List<AuthorityRule> rules); // 修改授权规则
官方 demo:Sentinel/sentinel-demo at master · alibaba/Sentinel (github.com)
基础示例 demo
熔断降级
在 sentinel 中熔断策略分为慢调用比例 (SLOW_REQUEST_RATIO),异常比例 (
ERROR_RATIO),异常数 (
ERROR_COUNT)
异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效
Sentinel 提供以下几种熔断策略
- 慢调用比例 (
SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(
statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
- 异常比例 (
ERROR_RATIO):当单位统计时长(
statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是
[0.0, 1.0],代表 0% - 100%。
- 异常数 (
ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
慢调用比例熔断 demo
具体应用
下面将会在 springboot 中使用配置文件配置规则
application. yml 配置流控和降级规则文件位置
spring: application: name: lin-cms-spring-boot cloud: sentinel: datasource: ds1: file: data-type: json file: 'classpath: flowrule.json' rule-type: flow ds2: file: data-type: json file: 'classpath: degraderule.json' rule-type: degrade # 立即加载 eager: true transport: dashboard: localhost:8849 #sentinel控制台的请求地址
然后配置规则
flowrule.json
[ { "resource": "getBook", "controlBehavior": 0, "count": 5, "grade": 1, "limitApp": "default", "strategy": 0 } ]
degraderule.json
[ { "resource": "getBooks", "limitApp": "default", "grade": 0, "count": 20, "slowRatioThreshold": 0.5, "minRequestAmount": 5, "statIntervalMs": 1000, "timeWindow": 10 } ]
具体规则及参数说明请看[该文档](circuit-breaking | Sentinel (sentinelguard.io))
参数对应常量值可以参考 RuleConstant,该类位于 com.alibaba.csp.sentinel.slots.block
public final class RuleConstant { public static final int FLOW_GRADE_THREAD = 0; //限流 基于线程数 public static final int FLOW_GRADE_QPS = 1; //限流 基于QPS public static final int DEGRADE_GRADE_RT = 0; //降级 代表一秒内该资源的平均响应时间 /** * Degrade by biz exception ratio in the current {@link IntervalProperty#INTERVAL} second(s). */ public static final int DEGRADE_GRADE_EXCEPTION_RATIO = 1; // 降级 异常比例 /** * Degrade by biz exception count in the last 60 seconds. */ public static final int DEGRADE_GRADE_EXCEPTION_COUNT = 2;// 降级, 异常数 public static final int AUTHORITY_WHITE = 0;// 认证, 白名单 public static final int AUTHORITY_BLACK = 1;// 认证, 黑名单 public static final int STRATEGY_DIRECT = 0; // 根据调用方限流策略 public static final int STRATEGY_RELATE = 1; // 关联流量限流策略 public static final int STRATEGY_CHAIN = 2; // 根据调用链入口限流策略 public static final int CONTROL_BEHAVIOR_DEFAULT = 0;// 限流行为,直接拒绝 public static final int CONTROL_BEHAVIOR_WARM_UP = 1;// 限流行为,WARM_UP public static final int CONTROL_BEHAVIOR_RATE_LIMITER = 2;// 限流行为,匀速排队 public static final int CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER = 3; public static final String LIMIT_APP_DEFAULT = "default"; public static final String LIMIT_APP_OTHER = "other"; public static final int DEFAULT_SAMPLE_COUNT = 2; public static final int DEFAULT_WINDOW_INTERVAL_MS = 1000; private RuleConstant() {} }
然后使用 Apifox 或是 JMeter 进行流控测试,可以看到 QPS 流控生效
微服务