一、GateWay网关规则持久化
1、介绍:Sentinel官方文档 | 动态规则扩展 | 推荐链接
2、下载源码Sentinel-1.8.0.zip,并解压
3、sentinel-dashboard项目注释pom.xml依赖(sentinel-datasource-nacos)作用域配置(<scope>test</scope>)
4、复制NacosConfig和NacosConfigUtil文件
5、修改NacosConfig的配置在这里插入图片描述
/**
* 网关API
*
* @return
* @throws Exception
*/
@Bean
public Converter<List<ApiDefinitionEntity>, String> apiDefinitionEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<ApiDefinitionEntity>> apiDefinitionEntityDecoder() {
return s -> JSON.parseArray(s, ApiDefinitionEntity.class);
}
/**
* 网关flowRule
*
* @return
* @throws Exception
*/
@Bean
public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<GatewayFlowRuleEntity>> gatewayFlowRuleEntityDecoder() {
return s -> JSON.parseArray(s, GatewayFlowRuleEntity.class);
}
@Bean
public ConfigService nacosConfigService() throws Exception {
Properties properties = new Properties();
// nacos 地址
properties.put(PropertyKeyConst.SERVER_ADDR, "101.101.101.101:7001");
// 命令空间
properties.put(PropertyKeyConst.NAMESPACE, "dev");
// nacos 账号
properties.put(PropertyKeyConst.USERNAME, "nacos");
// nacos 账号密码
properties.put(PropertyKeyConst.PASSWORD, "nacos");
return ConfigFactory.createConfigService(properties);
}
6、NacosConfigUtil文件中添加配置
public static final String GETWAY_FLOW_DATA_ID_POSTFIX = "-sentinel-gateway-flow-rules";
public static final String GETWAY_API_DATA_ID_POSTFIX = "-sentinel-gateway-api-rules";
7、创建GateWayFlowRulesNacosProvider、GateWayFlowRulesNacosPunlisher、GetWayApiNacosProvider、GetWayApiNacosPublisher文件。
package com.alibaba.csp.sentinel.dashboard.rule.gateway;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component("gateWayFlowRulesNacosProvider")
public class GateWayFlowRulesNacosProvider implements DynamicRuleProvider<List<GatewayFlowRuleEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<String, List<GatewayFlowRuleEntity>> converter;
@Override
public List<GatewayFlowRuleEntity> getRules(String appName) throws Exception {
String rules = configService.getConfig(appName + NacosConfigUtil.GETWAY_FLOW_DATA_ID_POSTFIX,
NacosConfigUtil.GROUP_ID, 3000);
if (StringUtil.isEmpty(rules)) {
return new ArrayList<>();
}
return converter.convert(rules);
}
}
package com.alibaba.csp.sentinel.dashboard.rule.gateway;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component("gateWayFlowRulesNacosPunlisher")
public class GateWayFlowRulesNacosPunlisher implements DynamicRulePublisher<List<GatewayFlowRuleEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<List<GatewayFlowRuleEntity>, String> converter;
@Override
public void publish(String app, List<GatewayFlowRuleEntity> rules) throws Exception {
AssertUtil.notEmpty(app, "app name cannot be empty");
if (rules == null) {
return;
}
configService.publishConfig(app + NacosConfigUtil.GETWAY_FLOW_DATA_ID_POSTFIX,
NacosConfigUtil.GROUP_ID, converter.convert(rules));
}
}
package com.alibaba.csp.sentinel.dashboard.rule.gateway;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component("getWayApiNacosProvider")
public class GetWayApiNacosProvider implements DynamicRuleProvider<List<ApiDefinitionEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<String , List<ApiDefinitionEntity>> converter;
@Override
public List<ApiDefinitionEntity> getRules(String appName) throws Exception {
String rules = configService.getConfig(appName+ NacosConfigUtil.GETWAY_API_DATA_ID_POSTFIX
,NacosConfigUtil.GROUP_ID,3000);
if(StringUtil.isEmpty(rules)){
return new ArrayList<>();
}
return converter.convert(rules);
}
}
package com.alibaba.csp.sentinel.dashboard.rule.gateway;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component("getWayApiNacosPublisher")
public class GetWayApiNacosPublisher implements DynamicRulePublisher<List<ApiDefinitionEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<List<ApiDefinitionEntity>, String> converter;
@Override
public void publish(String app, List<ApiDefinitionEntity> rules) throws Exception {
AssertUtil.notEmpty(app, "app name cannot be empty");
if (rules == null) {
return;
}
configService.publishConfig(app+ NacosConfigUtil.GETWAY_API_DATA_ID_POSTFIX,
NacosConfigUtil.GROUP_ID,converter.convert(rules));
}
}
8、修改GatewayApiController文件
8.1、新增依赖注入
//添加我们自己写的ruleProvider
@Autowired
@Qualifier("getWayApiNacosProvider")
private DynamicRuleProvider<List<ApiDefinitionEntity>> ruleProvider;
//添加我们自己写的 publisher
@Autowired
@Qualifier("getWayApiNacosPublisher")
private DynamicRulePublisher<List<ApiDefinitionEntity>> rulePublisher;
8.2、修改queryApis方法,替换为拉取Nacos配置
List<ApiDefinitionEntity> apis = ruleProvider.getRules(app);
8.3、新增方法并全局替换掉旧方法,涉及替换的方法:addApi、updateApi、deleteApi
/**
* 把配置推给nacos中
*
* @param app
* @throws Exception
*/
private void publishApis(String app) {
List<ApiDefinitionEntity> rules = repository.findAllByApp(app);
try {
rulePublisher.publish(app, rules);
} catch (Exception e) {
e.printStackTrace();
}
}
9、修改GatewayFlowRuleController文件,同上
9.1、新增依赖
//添加我们自己写的ruleProvider
@Autowired
@Qualifier("gateWayFlowRulesNacosProvider")
private DynamicRuleProvider<List<GatewayFlowRuleEntity>> ruleProvider;
//添加我们自己写的 publisher
@Autowired
@Qualifier("gateWayFlowRulesNacosPunlisher")
private DynamicRulePublisher<List<GatewayFlowRuleEntity>> rulePublisher;
9.2、修改queryApis方法,替换为拉取Nacos配置
List<GatewayFlowRuleEntity> rules = ruleProvider.getRules(app);
9.3、新增方法并全局替换掉旧方法,涉及替换的方法:addApi、updateApi、deleteApi
/**
* 把配置推给nacos中
*
* @param app
* @throws Exception
*/
private boolean publishRules(String app) {
List<GatewayFlowRuleEntity> rules = repository.findAllByApp(app);
try {
rulePublisher.publish(app, rules);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
10、重启服务
注意:存在Nacos修改规则后,列表不会自动刷新问题。
三、问题总结
1、NacosConfig配置中不支持账号和密码
版本问题,之前之后1.7.3版本就不支持账号和密码,后换了1.8.0版本。