目录
直接使用dashboard和sentinel配置各种规则时,默认是存在了内存直接使用dashboard和sentinel配置各种规则时,默认是存在了内存中。如果服务器重启那么数据就会丢失,从而Sentinel提供了5中持久化的方式,将各种配置数据进行持久化,若服务器重启就重新加载持久化的数据,防止数据丢失。
目前 Sentinel 中默认实现了5种规则持久化的方式,分别是:file、redis、nacos、zk和apollo。 可以在 sentinel 控制台中编辑 限流配置,并且同步到 nacos 做持久化。在 nacos 中修改了限流配置,也可以同步到 sentinel 控制台。
对sentinel中的配置进行持久化需要三步:
-
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
- <version>2.2.1.RELEASEversion>
- dependency>
-
- <dependency>
- <groupId>com.alibaba.cspgroupId>
- <artifactId>sentinel-datasource-nacosartifactId>
- <version>1.7.2version>
- dependency>
server:
port: 9000
spring:
application:
name: ORDER-SERVICE-COSTUMER
cloud:
#配置 nacos server 注册中心总的地址
nacos:
server-addr: localhost:8848 # 配置nacos server 注册中心地址
sentinel:
enabled: true #开启sentinel保护
transport:
dashboard: localhost:8080 #配置连接到 dashboard 的web的地址
port: 8719 #指定sentinel组件与 sentinel dashboard的TCP通信地址192.168.56.21:8719
datasource:
ds1: # 这个名字任意起
naccs:
server-addr: localhost:8848 # 配置nacos server 注册中心地址
dataId: ${spring.application.name} # 和nacos中保持对应
groupId: DEFAULT_GROUP # 和 nacos中保持对应
data-type: json # 规则类型:流控
rule-type: flow # 对于 nacos 数据类型
以资源进行限流为案例。
[
{
"resource": "/order/buy/{id}", #保护的资源
"limitApp": "default", #来源应用
"grade": 0, #阈值线程数 0表示阈值,1表示线程数
"count": 1, # 单机阈值
"strategy": 0, # 流控模式 0表示直接 1表示关联 2表示链路
"controlBehavior": 0, #0表示快速失败 1表示预热 2表示排队等待
"clusterMode": false #是否是集群
}
]
对应 sentinel中的规则如下图


Sentinel 为我们提供了两个接口来实现规则的持久化,他们分别是:ReadableDataSource 和 WritableDataSource。其中主要关注ReadableDataSource。
- public interface ReadableDataSource
{ - //将原始数据转换成我们所需的格式
- T loadConfig() throws Exception;
- //从数据源中读取原始的数据
- S readSource() 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 {
- T value = parser.convert(conf);
- return value;
- }
-
- @Override
- public SentinelProperty
getProperty() { - return property;
- }
- }
实际上每个具体的DataSource主要要做三件事情:
以Redis做持久化数据源为例。
- public RedisDataSource(RedisConnectionConfig connectionConfig, String ruleKey, String channel,
- Converter
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
stringRedisCommands = redisClient.connect().sync(); - return stringRedisCommands.get(ruleKey);
- }