上一篇文章我们已经对 Sentinel 有个简单的了解,接下来我们将讲解 Sentinel的具体使用。 Sentinel的使用分为两部分:
下面我们就分两部分来看,如果使用Sentinel来实现接口限流。
java -jar sentinel-dashboard-1.6.2.jar
sentinel-dashboard 不像Nacos的服务端那样还提供了外置配置文件,比较容易修改参数。不过没关系,由于 sentinel-dashboard是一个标准的SpringBoot应用,所以如果需要自定义端口号等配置的话,可以通过在启动参数中增加参数来调整,比如:-Dserver.port=8888
。
默认情况下,sentinel-dashboard以8080端口启动,所以可以通过访问: http://localhost:8080 来验证是否启动成功,如果一切顺利,可以看到如下界面:
注意: 只要 1.6.0 及以上的版本,才有这个简单的登录页面。默认用户名密码都是: sentinel
。对于用户登录相关的配置可在启动命令中添加下面参数来修改默认配置:
Dsentinel.dashboard.auth.username=sentinel
:用于指定控制台的登录用户名为 sentinel;Dsentinel.dashboard.auth.password=123456
:用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinelDserver.servlet.session.timeout=7200
:用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;输入用户名密码登录后,会看下如下页面:
第一步: 创建 alibaba-sentinel-rate-limiting
web应用,并在的pom.xml 中引入 Spring Cloud Alibaba的Sentinel模块依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
第二步: 在Spring Cloud 应用中 application.yml
配置 sentinel dashboard 的访问地址:
spring:
cloud:
sentinel:
transport:
# 指定sentinel控制台地址
dashboard: localhost:8080
控制台相关配置项:
配置项 | 默认值 | 最小值 | 描述 |
---|---|---|---|
sentinel.dashboard.app.hideAppNoMachineMillis | 0 | 60000 | 是否隐藏无健康节点的应用,距离最近一次主机心跳时间的毫秒数,默认关闭 |
sentinel.dashboard.removeAppNoMachineMillis | 0 | 120000 | 是否自动删除无健康节点的应用,距离最近一次其下节点的心跳时间毫秒数,默认关闭 |
sentinel.dashboard.unhealthyMachineMillis | 60000 | 30000 | 主机失联判定,不可关闭 |
sentinel.dashboard.autoRemoveMachineMillis | 0 | 300000 | 距离最近心跳时间超过指定时间是否自动删除失联节点,默认关闭 |
server.port | 8080 | - | 指定端口 |
csp.sentinel.dashboard.server | localhost:8080 | - | 指定地址 |
project.name | - | - | 指定程序的名称 |
sentinel.dashboard.auth.username [1.6版本支持] | sentinel | - | Sentinel Dashboard登录账号 |
sentinel.dashboard.auth.password [1.6版本支持] | sentinel | - | Sentinel Dashboard登录密码 |
server.servlet.session.timeout [1.6版本支持] | 30分钟 | - | 登录Session过期时间。配置为7200表示7200秒;配置为60m表示60分钟 |
控制台配置项需在启动命令中指定,例如指定账户密码,如下:
java -jar -Dsentinel.dashboard.auth.username=admin -Dsentinel.dashboard.auth.password=123456 sentinel-dashboard-1.6.3.jar
第三步: 创建应用rest接口:
@Slf4j
@RestController
public class UserController {
@GetMapping("/findById")
public String getUser(@RequestParam String id) {
return "hello sentinel dashboard";
}
}
第四步: 启动应用,然后通过 postman 访问:http://localhost:9005/findById接口。
sentinel 是懒加载应用的,所有这里需要通过postman先访问,才能在控制台看到应用客户端。
此时,在Sentinel Dashboard界面中就可以看到我们启动的这个服务以及接口调用的实时监控了。
在完成了上面配置以后,我们在 Sentinel 控制台的 alibaba-sentinel-rate-limiting
服务下,单击 簇点链路 菜单,可以看到如下页面:
点击 流控按钮,便可以为应用设置流控规则
image.png
链路模式稍微有些抽象,这里举个简单的例子说明一下。下图中有两个调用链路,图中的/test-b和/test-a实际就是两个接口,它们都调用了同一个common资源,所以/test-b和/test-a就称为common的入口资源:
此时我为common添加一个限流规则如下:
可以看到流控模式选择链路后,需要填写一个入口资源,我这里填的是/test-a,那么这意味着什么呢?意味着当/test-a的QPS达到该规则的阈值后,就会对/test-a限流,同时/test-b不会受到任何影响。说明这种流控模式可以针对接口级别的来源进行限流,而“针对来源”则是对微服务级别的来源进行限流。
com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController
点击降级按钮,便可以为应用设置降级规则
-Dcsp.sentinel.statistic.max.rt=xxx
修改】com.alibaba.csp.sentinel.slots.block.degradeDegradeRule#passCheck
(对降级的判断都在这个方法里完成)Sentinel默认显示的端点并不支持热点规则,要显示热点规则,需要自己添加代码:
@GetMapping("test")
@SentinelResource("test")
public String testHot(@RequestParam(required = false) String a,
@RequestParam(required = false) String b) {
return a + "-" + b;
}
点击热点按钮,便可以为test设置热点规则
在时间窗口以内,一旦该api指定索引的参数QPS达到了域名,就会触发限流
热点规则适用的场景:
使用热点规则需要注意的点:
热点规则相关源码: com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowChecker#passCheck(对热点参数规则的判断逻辑都在这个方法里)
阈值类型
仅对 Linux/Unix-like 机器生效
):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5
点击授权按钮,便可以为应用设置授权规则
资源名所代表的资源只允许流控应用中添加的微服务使用(白名单)、不允许使用(黑名单)
参数
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | 无 |
count | 限流阈值 | 无 |
grade | 限流阈值类型,QPS 或线程数模式 | QPS模式 |
limitApp | 流控针对的调用来源 | default,代表不区分调用来源 |
strategy | default,代表不区分调用来源 | 根据资源本身 |
controlBehavior | 流控效果(直接拒绝 / 排队等待 / 慢启动模式) | 直接拒绝 |
代码
private void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule(resourceName);
// 设置QPS阈值为20
rule.setCount(20);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
参数
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,即限流规则的作用对象 | 无 |
count | 阈值 | 无 |
grade | 降级模式,根据 RT 降级还是根据异常比例降级 | RT |
timeWindow | 降级的时间,单位为 s | 无 |
代码
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);
}
参数
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,必填 | 无 |
count | 限流阈值,必填 | 无 |
grade | 限流模式 | QPS 模式 |
durationInSec | 统计窗口时间长度(单位为秒) | 1s |
controlBehavior | 流控效果(支持快速失败和匀速排队模式) | 快速失败 |
maxQueueingTimeMs | 最大排队等待时长(仅在匀速排队模式生效) | 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));
参数
Field | 说明 | 默认值 |
---|---|---|
highestSystemLoad | 最大的 load1 | -1(不生效) |
avgRt | 所有入口流量的平均响应时间 | -1(不生效) |
maxThread | 入口流量的最大并发数 | -1(不生效) |
qpa | 所有入口资源的 QPS | -1(不生效) |
代码
private void initSystemRule() {
List<SystemRule> rules = new ArrayList<>();
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(10);
rules.add(rule);
SystemRuleManager.loadRules(rules);
}
参数
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,即限流规则的作用对象 | 无 |
limitApp | 对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB | default,代表不区分调用来源 |
strategy | 限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式 | AUTHORITY_WHITE |
代码
AuthorityRule rule = new AuthorityRule();
rule.setResource("test");
rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
rule.setLimitApp("appA,appB");
AuthorityRuleManager.loadRules(Collections.singletonList(rule));