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


沫言|Sentinel实战:规则持久化的5种方式规则丢失无论是通过硬编码的方式来更新规则 , 还是通过接入 Sentinel Dashboard 后 , 在页面上操作来更新规则 , 都无法避免一个问题 , 那就是服务重新后 , 规则就丢失了 , 因为默认情况下规则是保存在内存中的 。
Dashboard 是通过 transport 模块来获取每个 Sentinel 客户端中的规则的 , 获取到的规则通过 RuleRepository 接口保存在 Dashboard 的内存中 , 如果在 Dashboard 页面中更改了某个规则 , 也会调用 transport 模块提供的接口将规则更新到客户端中去 。
是想一种情况 , 客户端连接上 Dashboard 之后 , 我们在 Dashboard 上为客户端配置好了规则 , 并推送给了客户端 。 这时由于一些因素客户端出现异常 , 服务不可用了 , 当客户端恢复正常再次连接上 Dashboard 后 , 这时所有的规则都丢失了 , 我们还需要重新配置一遍规则 , 这肯定不是我们想要的 。
沫言|Sentinel实战:规则持久化的5种方式如上图所示 , 当 Sentinel 的客户端挂掉之后 , 保存在各个 RuleManager 中的规则都会付之一炬 , 所以在生产中是绝对不能这么做的 。
规则持久化原理那我们有什么办法能解决这个问题呢 , 其实很简单 , 那就是把原本保存在 RuleManager 内存中的规则 , 持久化一份副本出去 。 这样下次客户端重启后 , 可以从持久化的副本中把数据 load 进内存中 , 这样就不会丢失规则了 , 如下图所示:
沫言|Sentinel实战:规则持久化的5种方式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 AbstractDataSourceimplements 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();}@Overridepublic T loadConfig() throws Exception {return loadConfig(readSource());}public T loadConfig(S conf) throws Exception {return parser.convert(conf);}@Overridepublic SentinelProperty getProperty() {return property;}}


推荐阅读