SpringCloud入门实战(9)--Sentinel(1)--简介及基本使用
Sentinel是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。本文主要介绍Sentinel的基本使用,文中使用到的软件版本:Sentinel 1.3.2、Spring Boot 2.2.5.RELEASE、Spring Cloud Hoxton.SR3、Java 1.8.0_191。
1、简介
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
1.1、Sentinel特性
1.2、Sentinel组成部分
a、核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
b、控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
2、规则
Sentinel的所有规则都可以在内存中动态地查询及修改,修改之后立即生效。同时Sentinel也提供相关API,供您来定制自己的规则策略。Sentinel支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则和热点参数规则。
2.1、流量控制规则(FlowRule)
同一个资源可以同时有多个限流规则,检查规则时会依次检查。其重要属性:
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | |
count | 限流阈值 | |
grade | 限流阈值类型,QPS 模式(1)或并发线程数模式(0) | QPS 模式 |
limitApp | 流控针对的调用来源 | default ,代表不区分调用来源 |
strategy | 调用关系限流策略:直接、链路、关联 | 根据资源本身(直接) |
controlBehavior | 流控效果(直接拒绝/WarmUp/匀速+排队等待),不支持按调用关系限流 | 直接拒绝 |
clusterMode | 是否集群限流 | 否 |
编码方式定义规则:
private void initFlowQpsRule() { List<FlowRule> rules = new ArrayList<>(); FlowRule rule = new FlowRule(resourceName); // set limit qps to 20 rule.setCount(20); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setLimitApp("default"); rules.add(rule); FlowRuleManager.loadRules(rules); }
2.2、熔断降级规则(DegradeRule)
同一个资源可以同时有多个降级规则。其重要属性:
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,即规则的作用对象 | |
grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调用比例 |
count | 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值 | |
timeWindow | 熔断时长,单位为 s | |
minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 |
statIntervalMs | 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) | 1000 ms |
slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) |
编码方式定义规则:
private void initDegradeRule() { List<DegradeRule> rules = new ArrayList<>(); DegradeRule rule = new DegradeRule(); rule.setResource(KEY); // set threshold RT, 10 ms rule.setCount(10); rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); rule.setTimeWindow(10); rules.add(rule); DegradeRuleManager.loadRules(rules); }
2.3、系统保护规则(SystemRule)
Sentinel系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。其重要属性:
Field | 说明 | 默认值 |
---|---|---|
highestSystemLoad | load1 触发值,用于触发自适应控制阶段 |
-1 (不生效) |
avgRt | 所有入口流量的平均响应时间 | -1 (不生效) |
maxThread | 入口流量的最大并发数 | -1 (不生效) |
qps | 所有入口资源的 QPS | -1 (不生效) |
highestCpuUsage | 当前系统的 CPU 使用率(0.0-1.0) | -1 (不生效) |
编码方式定义规则:
private void initSystemRule() { List<SystemRule> rules = new ArrayList<>(); SystemRule rule = new SystemRule(); rule.setHighestSystemLoad(10); rules.add(rule); SystemRuleManager.loadRules(rules); }
2.4、访问控制规则(AuthorityRule)
很多时候,我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的访问控制(黑白名单)的功能。其重要属性:
resource:资源名,即规则的作用对象
limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB
strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式
编码方式定义规则:
AuthorityRule rule = new AuthorityRule(); rule.setResource("test"); rule.setStrategy(RuleConstant.AUTHORITY_WHITE); rule.setLimitApp("appA,appB"); AuthorityRuleManager.loadRules(Collections.singletonList(rule));
2.5、热点规则(ParamFlowRule)
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。其重要属性类似于流量控制规则:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,必填 | |
count | 限流阈值,必填 | |
grade | 限流模式 | QPS 模式 |
durationInSec | 统计窗口时间长度(单位为秒),1.6.0 版本开始支持 | 1s |
controlBehavior | 流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持 | 快速失败 |
maxQueueingTimeMs | 最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持 | 0ms |
paramIdx | 热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置 |
|
paramFlowItemList | 参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限制。仅支持基本类型和字符串类型 |
|
clusterMode | 是否是集群参数流控规则 | false |
clusterConfig | 集群流控相关配置 |
编码方式定义规则:
ParamFlowRule rule = new ParamFlowRule(resourceName) .setParamIdx(0) .setCount(5); // 针对 int 类型的参数 PARAM_B,单独设置限流 QPS 阈值为 10,而不是全局的阈值 5. ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B)) .setClassType(int.class.getName()) .setCount(10); rule.setParamFlowItemList(Collections.singletonList(item)); ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
3、使用
3.1、抛出异常方式使用
SphU包含了try-catch风格的 API。用这种方式,当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理。
3.1.1、引入依赖
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-annotation-aspectj</artifactId> <version>1.8.0</version> </dependency>
3.1.2、样例
package com.abc.demo.test; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.SphU; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import java.util.ArrayList; import java.util.List; public class Sentinel { public static void main(String[] args) { // 配置规则. initFlowRules(); test(); } private static void test() { while(true) { // 1.5.0 版本开始可以直接利用 try-with-resources 特性 Entry entry = null; try { entry = SphU.entry("HelloWorld"); // 被保护的逻辑 System.out.println("hello world"); //Thread.sleep(1000 * 10); } catch (BlockException ex) { // 处理被流控的逻辑 System.out.println("blocked!"); } catch (Exception e) { e.printStackTrace(); } finally { if (entry != null) entry.exit(); } } } private static void initFlowRules(){ List<FlowRule> rules = new ArrayList<>(); FlowRule rule = new FlowRule(); rule.setResource("HelloWorld"); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // Set limit QPS to 20. rule.setCount(10); rules.add(rule); FlowRuleManager.loadRules(rules); } }
3.2、结合Spring Cloud使用
3.2.1、引入依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.3.RELEASE</version> </dependency>
3.2.2、注解方式使用sentinel
@SentinelResource注解用来标识资源是否被限流、降级。
package com.abc.scdemo.server.service; import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import org.springframework.stereotype.Service; @Service public class SentinelService { @SentinelResource(value = "sentinel-test", blockHandler = "blockHandler", fallback = "fallback") public String test(long id) { // if (true) { // throw new RuntimeException("a"); // } return "test"; } /** * Block异常处理函数,用来处理Sentinel限流/熔断等错误 * 参数最后多一个BlockException,其余与原函数一致 */ public String blockHandler(long id, BlockException e) { e.printStackTrace(); return "blockHandler"; } /** * Fallback函数,用来处理接口中业务代码所有异常 * 函数签名与原函数一致或加一个 Throwable 类型的参数. */ public String fallback(long id) { return "fallback"; } }
package com.abc.scdemo.server.controller; import com.abc.scdemo.server.service.SentinelService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/sentinel") public class SentinelController { private Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private SentinelService service; @RequestMapping("/test") public String test(long id) { logger.info(id + ""); return service.test(id); } @RequestMapping("/test2") public String test2(long id) { logger.info(id + ""); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } return "test2"; } }
一般推荐将@SentinelResource注解加到服务实现上,而在Web层可以在snetinel控制台查看url并定义规则。
3.2.3、sentinel控制台
Sentinel控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。直接使用Spring Cloud Alibaba自带的Web埋点适配。
a、下载控制台的安装包
https://github.com/alibaba/Sentinel/releases
b、启动
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
c、控制台
http://10.49.196.10:8080/ 用户名/密码为:sentinel/sentinel
3.2.4、SpingCloud应用中配置Sentinel控制台地址
spring: cloud: sentinel: transport: port: 8719 dashboard: 10.49.196.10:8080 project: name: scdemo-server
启动应用后并访问响应的url,sentinel控制台会出现监控信息:
可以在对应的url后定义流控规则:
定义降级规则: