前言
到目前为止,我们的规则定义是这样的:
@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即可。
改造控制台
控制台关于流控的 Controller 在 com.alibaba.csp.sentinel.dashboard.controller.v2 包中 FlowControllerV2 ,FlowControllerV2 有两个对于流控规则数据的持久化接口(此处修改请注意,本文使用的控制台版本为1.8.6,在界面上设置流控规则,它提交的地址不是flow/v2,而是flow/v1)所以即便修改了如下接口,也无法实现,还需要修改控制台的前端代码。
@Autowired
@Qualifier("flowRuleDefaultProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleDefaultPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
控制台的test代码中有提供流控规则的示例代码,我们在此基础上进行扩展
看过控制台源码的朋友肯定明白,官网提供的控制台程序只提供了简单的实现而已,如果有需求、且资源时间足够,大家可以参考这个控制台源码进行自定义修改,后续我们会大概介绍Sentinel客户端和控制台之间的通信过程。
客户端从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 一文。