Sentinel 查看和定义规则

引言

在前面的文章中,我们已经简单地介绍了 Sentinel 中所包含的各类规则,本文将介绍 Sentinel 中各类规则的查看和修改方式,和 Sentinel 相关的所有文章均会收录于<Sentinel系列文章>中,感兴趣的同学可以看一下。

查看和修改规则

查询更改规则

引入了 transport 模块后,可以通过以下的 HTTP API 来获取所有已加载的规则:http://localhost:8719/getRules?type=<XXXX>

  • type=flow: 以 JSON 格式返回现有的限流规则
  • type=degrade: 返回现有生效的降级规则列表
  • type=system: 则返回系统保护规则。

获取所有热点规则:http://localhost:8719/getParamRules

修改规则

Sentinel 的理念是开发者只需要关注资源的定义,当资源定义成功后可以动态增加各种流控降级规则。Sentinel 提供两种方式修改规则:

  • 通过 API 直接修改 (loadRules)
  • 通过 DataSource 适配不同数据源修改

API 方式

手动通过 API 修改比较直观,可以通过以下几个 API 修改不同的规则:

1
2
3
4
// 修改流控规则
FlowRuleManager.loadRules(List<FlowRule> rules);
// 修改降级规则
DegradeRuleManager.loadRules(List<DegradeRule> rules);

上面的规则配置,都是存在内存中的。即如果应用重启,这个规则就会失效。所以一般仅用于测试和演示,生产上一般通过动态规则源的方式来动态管理规则,您可以通过实现 DataSource 接口的方式,来自定义规则的存储数据源。通常的建议有:

  • 整合动态配置系统,如 ZooKeeper、Nacos、Apollo 等,动态地实时刷新配置规则
  • 结合 RDBMS、NoSQL、VCS 等来实现该规则
  • 配合 Sentinel Dashboard 使用

DataSource 拓展

上述 loadRules() 方法只接受内存态的规则对象,但更多时候规则存储在文件、数据库或者配置中心当中。DataSource 接口给我们提供了对接任意配置源的能力。相比直接通过 API 修改规则,实现 DataSource 接口是更加可靠的做法。

我们推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现 ReadableDataSource 接口端监听规则中心实时获取变更,流程如下:
data-source
DataSource 扩展常见的实现方式有:

  • 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更。实现拉模式的数据源最简单的方式是继承 AutoRefreshDataSource 抽象类,然后实现 readSource() 方法,在该方法里从指定数据源读取字符串格式的配置数据。
  • 推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper、etcd 等配置中心。这种方式有更好的实时性和一致性保证。实现推模式的数据源最简单的方式是继承 AbstractDataSource 抽象类,在其构造方法中添加监听器,并实现 readSource() 从指定数据源读取字符串格式的配置数据。

通常需要调用以下方法将数据源注册至指定的规则管理器中:

1
2
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, parser);
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

若不希望手动注册数据源,可以借助 Sentinel 的 InitFunc SPI 扩展接口。只需要实现自己的 InitFunc 接口,在 init 方法中编写注册数据源的逻辑。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.test.init;

public class DataSourceInitFunc implements InitFunc {

@Override
public void init() throws Exception {
final String remoteAddress = "localhost";
final String groupId = "Sentinel:Demo";
final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule";

ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId,
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
}

接着将对应的类名添加到位于资源目录(通常是 resource 目录)下的 META-INF/services 目录下的 com.alibaba.csp.sentinel.init.InitFunc 文件中,比如我们将上述的 com.test.init.DataSourceInitFunc 添加到文件中。当初次访问任意资源的时候,Sentinel 就可以自动去注册对应的数据源了。

控制台

Sentinel 提供了一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。另外,它还提供了一定的鉴权功能。这里,我们将会详细讲述如何使用这些功能,以及如何让控制台配合 Sentinel 核心库一起工作。

Sentinel 控制台包含如下功能:

  • 查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
  • 监控 (单机和集群聚合):通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
  • 规则管理和推送:统一管理推送规则。
  • 鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。
启动

首先,您可以从 release 页面下载最新版本的控制台 jar 包。当然,您也可以从最新版本的源码自行构建 Sentinel 控制台:

  • 下载 控制台 工程
  • 使用以下命令将代码打包成一个 fat jar: mvn clean package

有了控制台的 jar 包之后,可以使用如下命令启动控制台:

1
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080。

客户端接入

控制台启动后,客户端要想接入控制台,需要引入 Transport 模块来与 Sentinel 控制台进行通信。您可以通过 pom.xml 引入 JAR 包:

1
2
3
4
5
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>x.y.z</version>
</dependency>

启动时加入 JVM 参数 -Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台地址和端口。若同一个机器上启动多个应用,则需要通过 -Dcsp.sentinel.api.port=xxxx 指定客户端监控 API 的端口(默认是 8719)。

Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。这里我以 Sentinel 提供的 dubbo demo 接入 dashboard 作为例子,正确配置 Provider 和 Consumer 的 JVM 参数后,就能在 dashboard 中看到 dubbo 服务的流量统计。

1
2
3
4
# Provider
-Djava.net.preferIPv4Stack=true -Dcsp.sentinel.api.port=8730 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=provider
# Consumer
-Djava.net.preferIPv4Stack=true -Dcsp.sentinel.api.port=8721 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=consumer

client-statistic

查看节点健康值

如果您能在机器列表中看到相应的的机器,就代表着这些服务已经成功接入控制台,如果没有看到相应的机器,请检查配置,并通过 ${user.home}/logs/csp/sentinel-record.log.xxx 日志来排查原因。回到我们上一步的例子中,当我我们正常启动 Provider 和 Consumer 服务后,就可以在 dashboard 的机器列表中看到我们的节点。
health-node
而当我们关闭 Consumer 服务并等待其超时后,就能在 dashboard 的机器列表中看到本地的 Consumer 服务已经失联。
unhealth-node

监控

簇点链路(单机调用链路)页面实时的去拉取指定客户端资源的运行情况。它一共提供两种展示模式:一种用树状结构展示资源的调用链路,另外一种则不区分调用链路展示资源的实时情况。

注意: 簇点链路监控是内存态的信息,它仅展示启动后调用过的资源。
link-statistic
同时,同一个服务下的所有机器的簇点信息会被汇总,并且秒级地展示在”实时监控”下。

注意: 实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。此外,请确保 Sentinel 控制台所在的机器时间与自己应用的机器时间保持一致,否则会导致拉不到实时的监控数据。
realtime-statistic

规则管理及推送

Sentinel 控制台同时提供简单的规则管理以及推送的功能。规则推送分为 3 种模式,包括 “原始模式”、”Pull 模式” 和”Push 模式”。

这里先简单的介绍”原始模式”。它主要是通过接入端暴露的 HTTP API 来查询。规则推送也是通过这些 HTTP API 来更改规则。这也意味着这些规则仅在内存态生效,应用重启之后,该规则会丢失。
change-rule
原始模式一般用于演示使用,在生产环境中,建议大家结合各种外部存储来定制自己的规则源,一般来说,大家都会通过控制台来进行规则写入和推送(推荐使用 PUSH 模式)。

Sentinel 控制台同时还提供了规则推送的示例页面(流控规则页面,前端路由为 /dashboard/v2/flow/xxx/),如果您想像我前面所说的那样用控制台进行数据源规则的修改的话,需要改造控制台的实现,对接上配置中心后就能直接通过 v2 页面推送规则至配置中心。Sentinel 控制台中已经对这部分内容进行了抽象,对应的接口如下:

  • DynamicRuleProvider<T>: 拉取规则(应用维度)
  • DynamicRulePublisher<T>: 推送规则(应用维度)

您只需实现 DynamicRuleProvider 和 DynamicRulePublisher 接口,并在 v2 的 Controller 中通过 @Qualifier 注解替换相应的 bean 即可实现应用维度推送。下面是控制台对接 ZooKeeper 配置中心的实现方案,您可以作为参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@Component("flowRuleZookeeperProvider")
public class FlowRuleZookeeperProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {

@Autowired
private CuratorFramework zkClient;
@Autowired
private Converter<String, List<FlowRuleEntity>> converter;

@Override
public List<FlowRuleEntity> getRules(String appName) throws Exception {
String zkPath = ZookeeperConfigUtil.getPath(appName);
Stat stat = zkClient.checkExists().forPath(zkPath);
if(stat == null){
return new ArrayList<>(0);
}
byte[] bytes = zkClient.getData().forPath(zkPath);
if (null == bytes || bytes.length == 0) {
return new ArrayList<>();
}
String s = new String(bytes);

return converter.convert(s);
}
}

@Component("flowRuleZookeeperPublisher")
public class FlowRuleZookeeperPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
@Autowired
private CuratorFramework zkClient;
@Autowired
private Converter<List<FlowRuleEntity>, String> converter;

@Override
public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
AssertUtil.notEmpty(app, "app name cannot be empty");

String path = ZookeeperConfigUtil.getPath(app);
Stat stat = zkClient.checkExists().forPath(path);
if (stat == null) {
zkClient.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, null);
}
byte[] data = CollectionUtils.isEmpty(rules) ? "[]".getBytes() : converter.convert(rules).getBytes();
zkClient.setData().forPath(path, data);
}
}

// com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2
@RestController
@RequestMapping(value = "/v2/flow")
public class FlowControllerV2 {

//...
@Autowired
@Qualifier("flowRuleZookeeperProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleZookeeperPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
//...
}

data-source

集群流控管理

Sentinel 1.4.1 版本的控制台引入了应用维度的集群流控管理页面,可以方便地从应用维度分配 token server、查看相关状态。我们可以在侧边栏点击“集群流控”,进入 Token Server 列表页面,可以查看当前应用下所有的 token server 列表及相关状态:
token-server-status
我们可以点击右上角的“添加 Token Server”按钮来添加新的 token server 并分配 client:
config-token-server-client

网关流控管理

Sentinel 1.6.3 引入了网关流控控制台的支持,用户可以直接在 Sentinel 控制台上查看 API Gateway 实时的 route 和自定义 API 分组监控,管理网关规则和 API 分组配置。

在 API Gateway 端,用户只需要在原有启动参数的基础上添加如下启动参数即可标记应用为 API Gateway 类型:-Dcsp.sentinel.app.type=1

添加了正确的启动参数并有访问量后,我们就可以在 Sentinel 上面看到对应的 API Gateway 了。同时,还可以查看实时的 route 和自定义 API 分组的监控和调用信息:
gateway-statistic
而且,在控制台中我们还能配置自定义的 API 分组,将一些 URL 匹配模式归为一个 API 分组:
gateway-custom-group
然后我们可以在控制台中,根据 Gateway 的 route ID 或自定义 API 分组配置网关流控规则:
gateway-rule

鉴权

从 Sentinel 1.5.0 开始,控制台提供通用的鉴权接口 AuthService,用户可根据需求自行实现。

从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel。
dashboard-login
用户可以通过如下参数进行配置:

  • -Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel;
  • -Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel;
  • -Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;

同样也可以直接在 Spring properties 文件中进行配置。部署多台控制台时,session 默认不会在各实例之间共享,这一块也需要自行改造。

参考内容

[1] Sentinel GitHub 仓库
[2] Sentinel 官方 Wiki
[3] Sentinel 1.6.0 网关流控新特性介绍
[4] Sentinel 微服务流控降级实践
[5] Sentinel 1.7.0 新特性展望
[6] Sentinel 为 Dubbo 服务保驾护航
[7] 在生产环境中使用 Sentinel
[8] Sentinel 与 Hystrix 的对比
[9] 大流量下的服务质量治理 Dubbo Sentinel初涉
[10] Alibaba Sentinel RESTful 接口流控处理优化
[11] 阿里 Sentinel 源码解析
[12] Sentinel 教程 by 逅弈
[13] Sentinel 专题文章 by 一滴水的坚持

贝克街的流浪猫 wechat
您的打赏将鼓励我继续分享!
  • 本文作者: 贝克街的流浪猫
  • 本文链接: https://www.beikejiedeliulangmao.top/middleware/sentinel/define-rule/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 创作声明: 本文基于上述所有参考内容进行创作,其中可能涉及复制、修改或者转换,图片均来自网络,如有侵权请联系我,我会第一时间进行删除。