规则持久化的5种方式

规则丢失

无论是通过硬编码的方式来更新规则,还是通过接入 Sentinel Dashboard 后,在页面上操作来更新规则,都无法避免一个问题,那就是服务重新后,规则就丢失了,因为默认情况下规则是保存在内存中的。

Dashboard 是通过 transport 模块来获取每个 Sentinel 客户端中的规则的,获取到的规则通过 RuleRepository 接口保存在 Dashboard 的内存中,如果在 Dashboard 页面中更改了某个规则,也会调用 transport 模块提供的接口将规则更新到客户端中去。

试想这样一种情况,客户端连接上 Dashboard 之后,我们在 Dashboard 上为客户端配置好了规则,并推送给了客户端。这时由于一些因素客户端出现异常,服务不可用了,当客户端恢复正常再次连接上 Dashboard 后,这时所有的规则都丢失了,我们还需要重新配置一遍规则,这肯定不是我们想要的。

如上图所示,当 Sentinel 的客户端挂掉之后,保存在各个 RuleManager 中的规则都会付之一炬,所以在生产中是绝对不能这么做的。

规则持久化原理

那我们有什么办法能解决这个问题呢,其实很简单,那就是把原本保存在 RuleManager 内存中的规则,持久化一份副本出去。这样下次客户端重启后,可以从持久化的副本中把数据 load 进内存中,这样就不会丢失规则了,如下图所示:

Sentinel 为我们提供了两个接口来实现规则的持久化,他们分别是:ReadableDataSource 和 WritableDataSource。

其中 WritableDataSource 不是我们本次关心的重点,或者说 WritableDataSource 并没有那么重要,因为通常各种持久化的数据源已经提供了具体的将数据持久化的方法了,我们只需要把数据从持久化的数据源中获取出来,转成我们需要的格式就可以了。

下面我们来看一下 ReadableDataSource 接口的具体的定义:public interface ReadableDataSource {

// 从数据源中读取原始的数据

S readSource() throws Exception;

// 将原始数据转换成我们所需的格式

T loadConfig() throws Exception;

// 获取该种数据源的SentinelProperty对象

SentinelProperty getProperty();

}

接口很简单,最重要的就是这三个方法,另外 Sentinel 还为我们提供了一个抽象类:AbstractDataSource,该抽象类中实现了两个方法,具体的数据源实现类只需要实现一个 readSource 方法即可,具体的代码如下:public abstract class AbstractDataSource

implements ReadableDataSource {

// Converter接口负责转换数据

protected final Converter parser;

// SentinelProperty接口负责触发PropertyListener

// 的configUpdate方法的回调

protected final SentinelProperty property;

public AbstractDataSource(Converter parser) {

if (parser == null) {

throw new IllegalArgumentException("parser can"t be null");

}

this.parser = parser;

this.property = new DynamicSentinelProperty();

}

@Override

public T loadConfig() throws Exception {

return loadConfig(readSource());

}

public T loadConfig(S conf) throws Exception {

return parser.convert(conf);

}

@Override

public SentinelProperty getProperty() {

return property;

}

}

实际上每个具体的 DataSource 实现类需要做三件事:实现 readSource 方法将数据源中的原始数据转换成我们可以处理的数据S

提供一个 Converter 来将数据S转换成最终的数据T

将最终的数据T更新到具体的 RuleManager 中去

我把规则是如何从数据源加载进 RuleManager 中去的完整流程浓缩成了下面这张图:

大家可以就着这张图对照着源码来看,可以很容易的弄明白这个过程,这里我就不再展开具体的源码讲了,有几点需要注意的是:规则的持久化配置中心可以是redis、nacos、zk、file等等任何可以持久化的数据源,只要能保证更新规则时,客户端能得到通知即可

规则的更新可以通过 Sentinel Dashboard 也可以通过各个配置中心自己的更新接口来操作

AbstractDataSource 中的 SentinelProperty 持有了一个 PropertyListener 接口,最终更新 RuleManager 中的规则是 PropertyListener 去做的

规则持久化

好了,知道了具体的原理了,下面我们就来讲解下如何来接入规则的持久化。

目前 Sentinel 中默认实现了5种规则持久化的方式,分别是:file、redis、nacos、zk和apollo。

下面我们对这5种方式一一进行了解,以持久化限流的规则为例。

File

文件持久化有一个问题就是文件不像其他的配置中心,数据发生变更后会发出通知,使用文件来持久化的话就需要我们自己定时去扫描文件,来确定文件是否发现了变更。

文件数据源是通过 FileRefreshableDataSource 类来实现的,他是通过文件的最后更新时间来判断规则是否发生变更的。

首先需要引入依赖:

com.alibaba.csp

sentinel->

x.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 的话,可以尝试这种方式。

Redis

Redis 数据源的实现类是 RedisDataSource。

首先引入依赖:

com.alibaba.csp

sentinel-datasource-redis

x.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<>(config, ruleKey, channel, parser);

FlowRuleManager.register2Property(redisDataSource.getProperty());

}

Nacos

Nacos 数据源的实现类是 NacosDataSource。

首先引入依赖:

com.alibaba.csp

sentinel-datasource-nacos

x.y.z

接入方法如下:private void init() throws Exception {

String remoteAddress = yourRemoteAddress();

String groupId = yourGroupId();

String dataId = yourDataId();

Converter> parser = source -> JSON.parseObject(source,new TypeReference>() {});

ReadableDataSource> nacosDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, parser);

FlowRuleManager.register2Property(nacosDataSource.getProperty());

}

Zk

Zk 数据源的实现类是 ZookeeperDataSource。

首先引入依赖:

com.alibaba.csp

sentinel-datasource-zookeeper

x.y.z

接入方法如下:private void init() throws Exception {

String remoteAddress = yourRemoteAddress();

String path = yourPath();

Converter> parser = source -> JSON.parseObject(source,new TypeReference>() {});

ReadableDataSource> zookeeperDataSource = new ZookeeperDataSource<>(remoteAddress, path, parser);

FlowRuleManager.register2Property(zookeeperDataSource.getProperty());

}

Apollo

Apollo 数据源的实现类是 ApolloDataSource。

首先引入依赖:

com.alibaba.csp

sentinel-datasource-apollo

x.y.z

接入方法如下:private void init() throws Exception {

String namespaceName = yourNamespaceName();

String ruleKey = yourRuleKey();

String defaultRules = yourDefaultRules();

Converter> parser = source -> JSON.parseObject(source,new TypeReference>() {});

ReadableDataSource> apolloDataSource = new ApolloDataSource<>(namespaceName, ruleKey, path, defaultRules);

FlowRuleManager.register2Property(apolloDataSource.getProperty());

}

可以看到5中持久化的方式基本上大同小异,主要还是对接每种配置中心,实现数据的转换,并且监听配置中心的数据变化,当接收到数据变化后能够及时的将最新的规则更新到 RuleManager 中去就可以了。

- END -

系列文章:Sentinel 原理-全解析

Sentinel 原理-调用链

Sentinel 原理-滑动窗口

Sentinel 实战-限流

Sentinel 实战-控制台

更多原创好文

请关注「逅弈逐码」

sentinel 时间窗口_Sentinel 实战-规则持久化相关推荐

  1. sentinel 时间窗口_Sentinel使用令牌桶实现预热【原理源码】

    前言 Sentinel的QPS流控效果有快速失败.预热模式.排队等待.预热+排队等待模式,本文主要分析预热模式中是如何使用令牌桶算法限流的. 一.流控效果源码结构 在FlowRule更新缓存时,根据配 ...

  2. sentinel 时间窗口_Sentinel潜龙勿用篇

    前言 我为什么写这篇文章,是因为Sentinel实在是太强大太好用了,再加上阿里开源,Sentinel的发展迅猛.已有多家公司生产使用,但但凡神功,一个不慎,就有可能走火入魔,轻则离职走人,重则走火入 ...

  3. sentinel 时间窗口_Sentinel滑动窗口算法

    在前面搞清楚了Sentinel的使用后,大致理了一下Sentinel的责任链,搞清楚了这个,基本就已经梳理清楚sentinel-core模块的大部分内容,顺着这条链路可以继续梳理很多东西. 知其然.知 ...

  4. sentinel 时间窗口的实现

    本文的github地址点击这里 获取时间窗口的主要流程 在 Sentinel 中,主要是通过 LeapArray 类来实现滑动时间窗口的实现和选择.在 sentinel 的这个获取时间窗口并为时间窗口 ...

  5. SpringCloud(14) Sentinel 1.8.4 规则持久化到Nacos

    文章目录 一.前言 二.快速体验 1.部署sentinel 2.SpringCloud中规则持久化到nacos 3.sentinel控制台操作测试 三.sentinel-dashboard源码修改 1 ...

  6. Sentinel 规则持久化到 apollo 配置中心

    Sentinel 规则默认是存储在内存中的,只要服务重启之后对应的规则也会消失,实际的生产中肯定是不允许这种操作,因此 Sentinel 官方推荐在生产架构中使用第三方数据源作为永久存储中心,比如 n ...

  7. sentinel 端口_Sentinel 实战控制台篇

    上篇文章我通过一个简单的例子和大家分享了怎么接入 sentinel 但是规则的配置是通过硬编码来实现的,这种方式比较原始,不能动态修改,本篇文章我将通过接入 sentinel 控制台来解决这个问题. ...

  8. Alibaba Sentinel规则持久化-拉模式-手把手教程【基于文件】

    文章目录 一.拉模式架构 二.原理简述 三.编写 3.1 加依赖 3.2 写代码 3.3 配置 四.优缺点分析 五.你可能会有的疑问 六.参考文档 七.案例测试 7.1. 添加流控规则 7.2. 服务 ...

  9. sentinel滑动时间窗口算法学习

    滑动时间窗口 先不说sentinel的算法实现,先说什么是滑动时间窗口, 我们在进行限流的时候,比如通过QPS进行限流,那假如我们以秒为单位,举个例子: 我设置了限流规则,qps是10 如果不使用滑动 ...

最新文章

  1. MonoDroid相关资源
  2. 2017最新nginx+keepalived+centos7安装配置过程
  3. ssh服务优化与客户端命令使用
  4. html5跟html4有什么区别,Html5和Html4的区别
  5. Android开发笔记(五十)定时器AlarmManager
  6. 把握今生 不要期待来世
  7. jmeter 连接 sqlite 进行压力测试
  8. dreamweaver 正则表达式为属性值加上双引号_IT兄弟连 HTML5教程 HTML5表单 新增的表单属性3...
  9. Oracle数据库删除重复的记录
  10. JSP简介和会话技术
  11. 计算机毕业设计Java物料生产管理系统(源码+系统+mysql数据库+Lw文档)
  12. 最近在做微信支付委托代扣交互图。总结了几点需要注意的地方,与大家分享一下
  13. 使用UDP遇到的问题小结
  14. 十二月各地中小企业扶持政策汇总
  15. 华为云云享专家申请流程
  16. Rate Limiting Algorithms (限流算法)
  17. Mac使用技巧/M1 Mac安装 PS 2021 闪退、卡启动界面解决方法
  18. 全国php工资城市排名,2019年各城市工资排行_2019年全国各城市最新工资排行出炉 想去哪玩来对...
  19. 个人网站搭建及IIS部署(2019/3/11)个人心得分享
  20. Unity3D+WebGL数据交互、传参

热门文章

  1. 钱大妈关闭所有北京门店:低估了北京市场的难度
  2. 8599元起!三星Galaxy Z Fold3/Flip3 5G折叠手机国行即将发货
  3. 你在支付宝上搞钱,“90后”却在相亲
  4. 因触屏故障 美国监管部门对15.9万辆特斯拉进行调查
  5. 飞书上线“程序员友好”功能 迎接1024程序员节
  6. 小米10至尊纪念版现身Geekbench跑分:今晚一起见证历史
  7. 最新5G标准必要专利声明量排名:中兴通讯位列全球前三
  8. 两次秒售罄的小米10,还能火爆多久?
  9. 李国庆深夜发“15条真相”回应:关于原生家庭、同性恋、1.3亿...
  10. 还有人买吗?苹果新一代iPod touch悄然发布:升级为A10芯片