- 直接使用dashboard和sentinel配置各种规则时,默认是存在了内存中。如果服务器重启那么数据就会丢失,从而Sentinel提供了5中持久化的方式,将各种配置数据进行持久化,若服务器重启就重新加载持久化的数据,防止数据丢失。
1、持久化原理
Sentinel 为我们提供了两个接口来实现规则的持久化,他们分别是:ReadableDataSource 和 WritableDataSource。其中主要关注ReadableDataSource。
public interface ReadableDataSource<S, T> {
//将原始数据转换成我们所需的格式
T loadConfig() throws Exception;
//从数据源中读取原始的数据
S readSource() throws Exception;
//获取该种数据源的SentinelProperty对象,数据变化监听器
SentinelProperty<T> getProperty();
}
Sentinel 还为我们提供了一个抽象类:AbstractDataSource,该抽象类中实现了两个方法,具体的数据源实现类只需要实现一个 readSource 方法即可。
public abstract class AbstractDataSource<S, T> implements ReadableDataSource<S, T> {
// Converter接口负责转换数据
protected final Converter<S, T> parser;
//SentinelProperty接口负责触发PropertyListener的configUpdate方法的回调
protected final SentinelProperty<T> property;
public AbstractDataSource(Converter<S, T> parser) {
if (parser == null) {
throw new IllegalArgumentException("parser can't be null");
}
this.parser = parser;
this.property = new DynamicSentinelProperty<T>();
}
@Override
public T loadConfig() throws Exception {
return loadConfig(readSource());
}
public T loadConfig(S conf) throws Exception {
T value = parser.convert(conf);
return value;
}
@Override
public SentinelProperty<T> getProperty() {
return property;
}
}
实际上每个具体的DataSource主要要做三件事情:
- 实现 readSource 方法将数据源中的原始数据转换成我们可以处理的数据S
- 提供一个 Converter 来将数据S转换成最终的数据T
- 将最终的数据T更新到具体的 RuleManager 中去。
以Redis做持久化数据源为例。
public RedisDataSource(RedisConnectionConfig connectionConfig, String ruleKey, String channel,
Converter<String, T> parser) {
super(parser);
this.redisClient = getRedisClient(connectionConfig);
this.ruleKey = ruleKey;
//从Redis中加载原数据
loadInitialConfig();
}
private void loadInitialConfig() {
try {
//调用AbstractDatasource的方法,父类会调用readSource方法获得原数据
T newValue = loadConfig();
//将加载的到的数据,通过监听器更新规则的数据
getProperty().updateValue(newValue);
} catch (Exception ex) {
RecordLog.warn("[RedisDataSource] Error when loading initial config", ex);
}
}
@Override
public String readSource() {
RedisCommands<String, String> stringRedisCommands = redisClient.connect().sync();
return stringRedisCommands.get(ruleKey);
}
2、持久化方式
目前 Sentinel 中默认实现了5种规则持久化的方式,分别是:file、redis、nacos、zk和apollo。