沫言|Sentinel实战:规则持久化的5种方式( 二 )

实际上每个具体的 DataSource 实现类需要做三件事:

  • 实现 readSource 方法将数据源中的原始数据转换成我们可以处理的数据S
  • 提供一个 Converter 来将数据S转换成最终的数据T
  • 将最终的数据T更新到具体的 RuleManager 中去
我把规则是如何从数据源加载进 RuleManager 中去的完整流程浓缩成了下面这张图:
沫言|Sentinel实战:规则持久化的5种方式大家可以就着这张图对照着源码来看 , 可以很容易的弄明白这个过程 , 这里我就不再展开具体的源码讲了 , 有几点需要注意的是:
  • 规则的持久化配置中心可以是redis、nacos、zk、file等等任何可以持久化的数据源 , 只要能保证更新规则时 , 客户端能得到通知即可
  • 规则的更新可以通过 Sentinel Dashboard 也可以通过各个配置中心自己的更新接口来操作
  • AbstractDataSource 中的 SentinelProperty 持有了一个 PropertyListener 接口 , 最终更新 RuleManager 中的规则是 PropertyListener 去做的
规则持久化好了 , 知道了具体的原理了 , 下面我们就来讲解下如何来接入规则的持久化 。
目前 Sentinel 中默认实现了5种规则持久化的方式 , 分别是:file、redis、nacos、zk和apollo 。
下面我们对这5种方式一一进行了解 , 以持久化限流的规则为例 。
File文件持久化有一个问题就是文件不像其他的配置中心 , 数据发生变更后会发出通知 , 使用文件来持久化的话就需要我们自己定时去扫描文件 , 来确定文件是否发现了变更 。
文件数据源是通过 FileRefreshableDataSource 类来实现的 , 他是通过文件的最后更新时间来判断规则是否发生变更的 。
首先需要引入依赖:
com.alibaba.cspsentinel-datasource-extensionx.y.z接入的方法如下:
private void init() throws Exception { // 保存了限流规则的文件的地址 String flowRuleName = yourFlowRuleFileName(); Converter> parser = source -> JSON.parseObject(source,new TypeReference>() {});// 创建文件规则数据源FileRefreshableDataSource> flowRuleDataSource = new FileRefreshableDataSource<>(flowRuleName, parser);// 将Property注册到 RuleManager 中去FlowRuleManager.register2Property(flowRuleDataSource.getProperty());}PS:需要注意的是 , 我们需要在系统启动的时候调用该数据源注册的方法 , 否则不会生效的 。 具体的方式有很多 , 可以借助 Spring 来初始化该方法 , 也可以自定义一个类来实现 Sentinel 中的 InitFunc 接口来完成初始化 。
Sentinel 会在系统启动的时候通过 spi 来扫描 InitFunc 的实现类 , 并执行 InitFunc 的 init 方法 , 所以这也是一种可行的方法 , 如果我们的系统没有使用 Spring 的话 , 可以尝试这种方式 。
RedisRedis 数据源的实现类是 RedisDataSource 。
首先引入依赖:
com.alibaba.cspsentinel-datasource-redisx.y.z接入方法如下:
private void init() throws Exception { String redisHost = yourRedisHost(); String redisPort = yourRedisPort();String ruleKey = yourRuleKey();String channel = yourChannel(); Converter> parser = source -> JSON.parseObject(source,new TypeReference>() {});RedisConnectionConfig config = RedisConnectionConfig.builder().withHost(redisHost).withPort(redisPort).build();ReadableDataSource> redisDataSource = new RedisDataSource


推荐阅读