1、引入pom
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>${sentinel.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.csp/sentinel-datasource-consul -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-consul</artifactId>
<version>${sentinel-datasource-consul.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
2、增加配置文件相关配置
cloud:
consul:
# Consul server address
host: a.b.c.d
port: xx
# Configuration center related configuration
config:
# Enable configuration center, default value is true
enabled: true
# Set the basic folder of the configuration. The default value of config can be understood as the outermost folder of the configuration file
prefix: config
# Set the folder name of the application. The default value of application is generally recommended to be set as the microservice application name
default-context: sms
# Specify the configuration format as yaml
format: YAML
# The Key in Key/Values of Consul corresponds to the entire configuration file
data-key: bfms-sms-sentinel
# The above configuration can be understood as: load the configuration information corresponding to the Value whose Key is orderServiceConfig under the config/orderService / folder
watch:
# Whether to enable automatic refresh? The default value is true
enabled: true
# Refresh rate in milliseconds, default 1000
delay: 1000
name: application
sentinel:
transport:
dashboard: localhost:8080
port: 8720 #客户端监控API的端口
eager: true #取消Sentinel控制台懒加载
3、新增spi文件夹com.alibaba.csp.sentinel.init.InitFunc
注意路径
4、增加配置类ConsulDataSourceInitFunc
注意修改地址跟端口还有文件路径
package com.aspirecn.bfms.sms.config.sentinel;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.datasource.consul.ConsulDataSource;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.fastjson.JSON;
import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.kv.model.PutParams;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* sentinel和 consul 实现双向持久化
*/
@Component
@Slf4j
public class ConsulDataSourceInitFunc implements InitFunc {
private static final String CONSUL_SERVER_ADDRESS = "x.x.x.x"; // Consul 服务器地址
private static final int CONSUL_SERVER_PORT = xxxx; // Consul 服务器端口
private static final int DATA_SOURCE_REFRESH_INTERVAL = 5000; // 数据源刷新间隔(毫秒)
private static final String RULE_KEY = "config/sms"; // 规则键前缀
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); // 调度执行器服务
// 规则解析器
Converter<String, List<FlowRule>> flowRuleParser = createRuleParser(FlowRule.class);
Converter<String, List<DegradeRule>> degradeRuleParser = createRuleParser(DegradeRule.class);
Converter<String, List<SystemRule>> systemRuleParser = createRuleParser(SystemRule.class);
Converter<String, List<AuthorityRule>> authorityRuleParser = createRuleParser(AuthorityRule.class);
Converter<String, List<ParamFlowRule>> paramFlowRuleParser = createRuleParser(ParamFlowRule.class);
// Consul 可写数据源
private WritableDataSource<List<FlowRule>> flowRuleConsulWritableDataSource;
private WritableDataSource<List<DegradeRule>> degradeRuleConsulWritableDataSource;
private WritableDataSource<List<SystemRule>> systemRuleConsulWritableDataSource;
private WritableDataSource<List<AuthorityRule>> authorityRuleConsulWritableDataSource;
private WritableDataSource<List<ParamFlowRule>> paramFlowRuleConsulWritableDataSource;
@Override
public void init() throws Exception {
log.info("Initializing Sentinel rules from Consul");
// 创建 Consul 可读数据源
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = createConsulDataSource(RULE_KEY + "/flow-rule", flowRuleParser);
ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource = createConsulDataSource(RULE_KEY + "/degrade-rule", degradeRuleParser);
ReadableDataSource<String, List<SystemRule>> systemRuleDataSource = createConsulDataSource(RULE_KEY + "/system-rule", systemRuleParser);
ReadableDataSource<String, List<AuthorityRule>> authorityRuleDataSource = createConsulDataSource(RULE_KEY + "/authority-rule", authorityRuleParser);
ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleDataSource = createConsulDataSource(RULE_KEY + "/param-flow-rule", paramFlowRuleParser);
// 注册规则
registerFlowRules(flowRuleDataSource);
registerDegradeRules(degradeRuleDataSource);
registerSystemRules(systemRuleDataSource);
registerAuthorityRules(authorityRuleDataSource);
registerParamFlowRules(paramFlowRuleDataSource);
// 创建 Consul 可写数据源
createFlowRuleConsulWritableDataSource(flowRuleParser);
createDegradeRuleConsulWritableDataSource(degradeRuleParser);
createSystemRuleConsulWritableDataSource(systemRuleParser);
createAuthorityRuleConsulWritableDataSource(authorityRuleParser);
createParamFlowRuleConsulWritableDataSource(paramFlowRuleParser);
// 定时向 Consul 写入规则
scheduler.scheduleAtFixedRate(this::writeFlowRulesToConsul, 0, DATA_SOURCE_REFRESH_INTERVAL, TimeUnit.MILLISECONDS);
scheduler.scheduleAtFixedRate(this::writeDegradeRulesToConsul, 0, DATA_SOURCE_REFRESH_INTERVAL, TimeUnit.MILLISECONDS);
scheduler.scheduleAtFixedRate(this::writeSystemRulesToConsul, 0, DATA_SOURCE_REFRESH_INTERVAL, TimeUnit.MILLISECONDS);
scheduler.scheduleAtFixedRate(this::writeAuthorityRulesToConsul, 0, DATA_SOURCE_REFRESH_INTERVAL, TimeUnit.MILLISECONDS);
scheduler.scheduleAtFixedRate(this::writeParamFlowRulesToConsul, 0, DATA_SOURCE_REFRESH_INTERVAL, TimeUnit.MILLISECONDS);
log.info("Sentinel 规则 Consul 双向更新初始化完成");
}
private <T> Converter<String, List<T>> createRuleParser(Class<T> ruleClass) {
return source -> JSON.parseArray(source, ruleClass);
}
private <T> ReadableDataSource<String, List<T>> createConsulDataSource(String key, Converter<String, List<T>> parser) {
return new ConsulDataSource<>(CONSUL_SERVER_ADDRESS, CONSUL_SERVER_PORT, key, DATA_SOURCE_REFRESH_INTERVAL, parser);
}
private void registerFlowRules(ReadableDataSource<String, List<FlowRule>> flowRuleDataSource) {
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
private void registerDegradeRules(ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource) {
DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());
}
private void registerSystemRules(ReadableDataSource<String, List<SystemRule>> systemRuleDataSource) {
SystemRuleManager.register2Property(systemRuleDataSource.getProperty());
}
private void registerAuthorityRules(ReadableDataSource<String, List<AuthorityRule>> authorityRuleDataSource) {
AuthorityRuleManager.register2Property(authorityRuleDataSource.getProperty());
}
private void registerParamFlowRules(ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleDataSource) {
ParamFlowRuleManager.register2Property(paramFlowRuleDataSource.getProperty());
}
private void createFlowRuleConsulWritableDataSource(Converter<String, List<FlowRule>> flowRuleParser) {
flowRuleConsulWritableDataSource = new FlowRuleConsulWritableDataSource(CONSUL_SERVER_ADDRESS, CONSUL_SERVER_PORT, "/flow-rule", flowRuleParser);
}
private void createDegradeRuleConsulWritableDataSource(Converter<String, List<DegradeRule>> degradeRuleParser) {
degradeRuleConsulWritableDataSource = new DegradeRuleConsulWritableDataSource(CONSUL_SERVER_ADDRESS, CONSUL_SERVER_PORT, "/degrade-rule", degradeRuleParser);
}
private void createSystemRuleConsulWritableDataSource(Converter<String, List<SystemRule>> systemRuleParser) {
systemRuleConsulWritableDataSource = new SystemRuleConsulWritableDataSource(CONSUL_SERVER_ADDRESS, CONSUL_SERVER_PORT, "/system-rule", systemRuleParser);
}
private void createAuthorityRuleConsulWritableDataSource(Converter<String, List<AuthorityRule>> authorityRuleParser) {
authorityRuleConsulWritableDataSource = new AuthorityRuleConsulWritableDataSource(CONSUL_SERVER_ADDRESS, CONSUL_SERVER_PORT, "/authority-rule", authorityRuleParser);
}
private void createParamFlowRuleConsulWritableDataSource(Converter<String, List<ParamFlowRule>> paramFlowRuleParser) {
paramFlowRuleConsulWritableDataSource = new ParamRuleConsulWritableDataSource(CONSUL_SERVER_ADDRESS, CONSUL_SERVER_PORT, "/param-flow-rule", paramFlowRuleParser);
}
private void writeFlowRulesToConsul() {
List<FlowRule> flowRules = FlowRuleManager.getRules();
if (flowRules != null) {
try {
flowRuleConsulWritableDataSource.write(flowRules);
} catch (Exception e) {
log.error("Failed to write flow rules to Consul", e);
}
}
}
private void writeDegradeRulesToConsul() {
List<DegradeRule> degradeRules = DegradeRuleManager.getRules();
if (degradeRules != null) {
try {
degradeRuleConsulWritableDataSource.write(degradeRules);
} catch (Exception e) {
log.error("Failed to write degrade rules to Consul", e);
}
}
}
private void writeSystemRulesToConsul() {
List<SystemRule> systemRules = SystemRuleManager.getRules();
if (systemRules != null) {
try {
systemRuleConsulWritableDataSource.write(systemRules);
} catch (Exception e) {
log.error("Failed to write system rules to Consul", e);
}
}
}
private void writeAuthorityRulesToConsul() {
List<AuthorityRule> authorityRules = AuthorityRuleManager.getRules();
if (authorityRules != null) {
try {
authorityRuleConsulWritableDataSource.write(authorityRules);
} catch (Exception e) {
log.error("Failed to write authority rules to Consul", e);
}
}
}
private void writeParamFlowRulesToConsul() {
List<ParamFlowRule> paramFlowRules = ParamFlowRuleManager.getRules();
if (paramFlowRules != null) {
try {
paramFlowRuleConsulWritableDataSource.write(paramFlowRules);
} catch (Exception e) {
log.error("Failed to write param flow rules to Consul", e);
}
}
}
@Slf4j
public static class FlowRuleConsulWritableDataSource implements WritableDataSource<List<FlowRule>> {
private static final String RULE_KEY_PREFIX = "config/sms";
private final ConsulClient consulClient;
private final String ruleKey;
public FlowRuleConsulWritableDataSource(String consulServerAddress, int consulServerPort, String ruleKey, Converter<String, List<FlowRule>> flowRuleParser) {
this.consulClient = new ConsulClient(consulServerAddress, consulServerPort);
this.ruleKey = ruleKey;
}
@Override
public void write(List<FlowRule> flowRules) throws Exception {
String formattedFlowRules = formatFlowRules(flowRules);
String keyValue = RULE_KEY_PREFIX + "/" + ruleKey;
consulClient.setKVValue(keyValue, formattedFlowRules, new PutParams());
log.info("Flow rules written to Consul: {}", com.alibaba.fastjson2.JSON.parseObject(formattedFlowRules, String.class));
}
@Override
public void close() throws Exception {
// 关闭资源(如果有需要)
}
private String formatFlowRules(List<FlowRule> flowRules) {
ObjectMapper objectMapper = new ObjectMapper();
ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
try {
return objectWriter.writeValueAsString(flowRules);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
}
@Slf4j
public static class DegradeRuleConsulWritableDataSource implements WritableDataSource<List<DegradeRule>> {
private static final String RULE_KEY_PREFIX = "config/sms";
private final ConsulClient consulClient;
private final String ruleKey;
public DegradeRuleConsulWritableDataSource(String consulServerAddress, int consulServerPort, String ruleKey, Converter<String, List<DegradeRule>> flowRuleParser) {
this.consulClient = new ConsulClient(consulServerAddress, consulServerPort);
this.ruleKey = ruleKey;
}
@Override
public void write(List<DegradeRule> value) throws Exception {
String formattedFlowRules = formatDegradeRules(value);
String keyValue = RULE_KEY_PREFIX + "/" + ruleKey;
consulClient.setKVValue(keyValue, formattedFlowRules, new PutParams());
log.info("Flow rules written to Consul: {}", com.alibaba.fastjson2.JSON.parseObject(formattedFlowRules, String.class));
}
@Override
public void close() throws Exception {
// 关闭资源(如果有需要)
}
private String formatDegradeRules(List<DegradeRule> degradeRules) {
ObjectMapper objectMapper = new ObjectMapper();
ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
try {
return objectWriter.writeValueAsString(degradeRules);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
}
@Slf4j
public static class AuthorityRuleConsulWritableDataSource implements WritableDataSource<List<AuthorityRule>> {
private static final String RULE_KEY_PREFIX = "config/sms";
private final ConsulClient consulClient;
private final String ruleKey;
public AuthorityRuleConsulWritableDataSource(String consulServerAddress, int consulServerPort, String ruleKey, Converter<String, List<AuthorityRule>> flowRuleParser) {
this.consulClient = new ConsulClient(consulServerAddress, consulServerPort);
this.ruleKey = ruleKey;
}
@Override
public void write(List<AuthorityRule> flowRules) throws Exception {
String formattedFlowRules = formatFlowRules(flowRules);
String keyValue = RULE_KEY_PREFIX + "/" + ruleKey;
consulClient.setKVValue(keyValue, formattedFlowRules, new PutParams());
log.info("Flow rules written to Consul: {}", com.alibaba.fastjson2.JSON.parseObject(formattedFlowRules, String.class));
}
@Override
public void close() throws Exception {
// 关闭资源(如果有需要)
}
private String formatFlowRules(List<AuthorityRule> flowRules) {
ObjectMapper objectMapper = new ObjectMapper();
ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
try {
return objectWriter.writeValueAsString(flowRules);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
}
@Slf4j
public static class ParamRuleConsulWritableDataSource implements WritableDataSource<List<ParamFlowRule>> {
private static final String RULE_KEY_PREFIX = "config/sms";
private final ConsulClient consulClient;
private final String ruleKey;
public ParamRuleConsulWritableDataSource(String consulServerAddress, int consulServerPort, String ruleKey, Converter<String, List<ParamFlowRule>> flowRuleParser) {
this.consulClient = new ConsulClient(consulServerAddress, consulServerPort);
this.ruleKey = ruleKey;
}
@Override
public void write(List<ParamFlowRule> flowRules) throws Exception {
String formattedFlowRules = formatFlowRules(flowRules);
String keyValue = RULE_KEY_PREFIX + "/" + ruleKey;
consulClient.setKVValue(keyValue, formattedFlowRules, new PutParams());
log.info("Flow rules written to Consul: {}", com.alibaba.fastjson2.JSON.parseObject(formattedFlowRules, String.class));
}
@Override
public void close() throws Exception {
// 关闭资源(如果有需要)
}
private String formatFlowRules(List<ParamFlowRule> flowRules) {
ObjectMapper objectMapper = new ObjectMapper();
ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
try {
return objectWriter.writeValueAsString(flowRules);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
}
@Slf4j
public static class SystemRuleConsulWritableDataSource implements WritableDataSource<List<SystemRule>> {
private static final String RULE_KEY_PREFIX = "config/sms";
private final ConsulClient consulClient;
private final String ruleKey;
public SystemRuleConsulWritableDataSource(String consulServerAddress, int consulServerPort, String ruleKey, Converter<String, List<SystemRule>> flowRuleParser) {
this.consulClient = new ConsulClient(consulServerAddress, consulServerPort);
this.ruleKey = ruleKey;
}
@Override
public void write(List<SystemRule> flowRules) throws Exception {
String formattedFlowRules = formatFlowRules(flowRules);
String keyValue = RULE_KEY_PREFIX + "/" + ruleKey;
consulClient.setKVValue(keyValue, formattedFlowRules, new PutParams());
log.info("Flow rules written to Consul: {}", com.alibaba.fastjson2.JSON.parseObject(formattedFlowRules, String.class));
}
@Override
public void close() throws Exception {
// 关闭资源(如果有需要)
}
private String formatFlowRules(List<SystemRule> flowRules) {
ObjectMapper objectMapper = new ObjectMapper();
ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
try {
return objectWriter.writeValueAsString(flowRules);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
}
}
测试验证无误