前言
到目前为止,我们的规则定义是这样的:
@PostConstruct
public void initRole(){
List<FlowRule> rules = new ArrayList<>(1);
FlowRule rule = new FlowRule();
// 设置规则匹配的资源名称
rule.setResource("myFlowResource");
// 规则作用类型(此为QPS类型,还有一种为FLOW_GRADE_THREAD,线程数类型)
// 默认为QPS类型
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 按Grade设置,此处为限制 QPS 为 2.
rule.setCount(2);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
是使用Java硬编码的方式来定义规则,所有的规则定义都定义在内存中,这样定义无法动态的修改以及持久化规则。
Sentinel 提供两种方式修改规则:
- 通过 API 直接修改 (loadRules) – 即为我们示例的使用方式
- 通过 DataSource 适配不同数据源修改(推荐的使用方式)
DataSource 扩展
规则的推送方式
-
原始模式:API 将规则推送至客户端并直接更新到内存中,扩展写数据源(WritableDataSource)不保证一致性;规则保存在内存中,重启即消失
-
拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等。扩展写数据源(WritableDataSource)。不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题。
-
推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用 push 模式的数据源。扩展读数据源(ReadableDataSource)。
推模式支持的数据源有:ZooKeeper, Redis, Nacos, Apollo, etcd等
本文只介绍Nacos实现的推模式。
Nacos实现推模式
Nacos实现推模式主要分为两部分
-
客户端从Nacos获取规则
-
Sentinel控制台发布规则到Nacos(需对控制台代码进行改造,所以前篇我们建议使用源码打包方式部署Sentinel控制台。控制台默认规则发布等操作都是存在内存的,重启无效。关于控制台的改造后续我们对控制台进行详细讲解的时候再说,此处我们就直接发布到 Nacos 就行,不一定要用到控制台来做规则发布)
- 如果不用控制台,其实也可以,只要按照规则将规则配置发布到Nacos即可。
客户端从Nacos获取规则
只需将规则的定义代码修改为如下即可
// remoteAddress 代表 Nacos 服务端的地址
// groupId 和 dataId 对应 Nacos 中相应配置
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource =
new NacosDataSource<>(remoteAddress , groupId ,dataId ,
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>(){}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
示例中为流控规则 List<FlowRule> ,要定义 DegradeRule 只需要替换一些参数即可。
NacosDataSource 构造函数最后一个参数为 数据转换类,我们这里定义的json转换而已,最终看你的数据在Nacos中是什么表示。
示例规则
Nacos配置
客户端规则初始化代码
@PostConstruct
public void initRole(){
Properties nacosPro = new Properties();
nacosPro.put(PropertyKeyConst.SERVER_ADDR,"127.0.0.1:8848");
// 命令空间,如果你是使用的默认public,此处可以不用配置
nacosPro.put(PropertyKeyConst.NAMESPACE,"855e91a2-60e7-48c3-aa3f-27aa2f8a0f73");
// remoteAddress 代表 Nacos 服务端的地址
// groupId 和 dataId 对应 Nacos 中相应配置
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource =
new NacosDataSource<>(nacosPro, "Sentinel_Demo_Group", "com.yyoo.sentinel.demo.FlowRule",
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>(){}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
此处它的底层代码就是Nacos的 java SDK代码。本文不做过多介绍了,需要的可以参考我们 Nacos的Java SDK 一文。
通过API查询客户端当前的生效规则
http://localhost:8719/getRules?type=<XXXX>
- type=flow 以 JSON 格式返回现有的限流规则
- type=degrade 返回现有生效的降级规则列表
- type=system 则返回系统保护规则
获取热点规则
http://localhost:8719/getParamRules
Spring Boot / Spring Cloud 环境下配置动态数据源
spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json
spring.cloud.sentinel.datasource.ds1.file.rule-type=flow
#spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json
#spring.cloud.sentinel.datasource.ds1.file.data-type=custom
#spring.cloud.sentinel.datasource.ds1.file.converter-class=com.alibaba.cloud.examples.JsonFlowRuleListConverter
#spring.cloud.sentinel.datasource.ds1.file.rule-type=flow
spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848
spring.cloud.sentinel.datasource.ds2.nacos.data-id=sentinel
spring.cloud.sentinel.datasource.ds2.nacos.group-id=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds2.nacos.data-type=json
spring.cloud.sentinel.datasource.ds2.nacos.rule-type=degrade
spring.cloud.sentinel.datasource.ds3.zk.path = /Sentinel-Demo/SYSTEM-CODE-DEMO-FLOW
spring.cloud.sentinel.datasource.ds3.zk.server-addr = localhost:2181
spring.cloud.sentinel.datasource.ds3.zk.rule-type=authority
spring.cloud.sentinel.datasource.ds4.apollo.namespace-name = application
spring.cloud.sentinel.datasource.ds4.apollo.flow-rules-key = sentinel
spring.cloud.sentinel.datasource.ds4.apollo.default-flow-rule-value = test
spring.cloud.sentinel.datasource.ds4.apollo.rule-type=param-flow
d1, ds2, ds3, ds4 是 ReadableDataSource 的名字,可随意编写。后面的 file ,zk ,nacos , apollo 就是对应具体的数据源,它们后面的配置就是这些具体数据源各自的配置。注意数据源的依赖要单独引入(比如 Nacos 数据源需要单独引入 sentinel-datasource-nacos)
data-type 配置项表示 Converter 类型,Spring Cloud Alibaba Sentinel 默认提供两种内置的值,分别是 json 和 xml (不填默认是json)。 如果不想使用内置的 json 或 xml 这两种 Converter,可以填写 custom 表示自定义 Converter,然后再配置 converter-class 配置项,该配置项需要写类的全路径名(比如 spring.cloud.sentinel.datasource.ds1.file.converter-class=com.alibaba.cloud.examples.JsonFlowRuleListConverter)。
rule-type 配置表示该数据源中的规则属于哪种类型的规则(flow, degrade, authority, system, param-flow, gw-flow, gw-api-group)。注意网关流控规则 (GatewayFlowRule) 对应 gw-flow。
- 当某个数据源规则信息加载失败的情况下,不会影响应用的启动,会在日志中打印出错误信息。
- 默认情况下,xml 格式是不支持的。需要添加 jackson-dataformat-xml 依赖后才会自动生效。
- 如果规则加载没有生效,有可能是 jdk 版本导致的