使用nacos作为规则数据的存储中心,在服务启动的时候从配置中心拉取数据到本地,并讲规则加载到内存中;当在控制台修改规则时将数据推送到配置中心将数据更新。
nacos规则加载
//动态加载nacos的规则配置
private static void initRule() {
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, remoteAddress);
properties.put(PropertyKeyConst.NAMESPACE, NACOS_NAMESPACE_ID);
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties, groupId, flow_dataId,
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
ReadableDataSource<String, List<DegradeRule>> DegradeRuleDataSource = new NacosDataSource<>(properties, groupId, degrade_dataId,
source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
}));
DegradeRuleManager.register2Property(DegradeRuleDataSource.getProperty());
}
上面的代码中加载了熔断和流控的规则,如果需要其他的规则只需通过NacosDataSource类将对应的规则从nacos中拉取到本地,并使用对应的RuleManager注册就可以了,当规则中心数据发生变化时会自动同步到本地并刷新规则
在使用spring mvc中集成nacos还需要加上对应的拦截器才行
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// Add Sentinel interceptor
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
//限流处理器
config.setBlockExceptionHandler(new DefaultBlockExceptionHandler());
//注册限流拦截器
registry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**");
}
}
这样spring mvc基于nacos的简易sentinel流控就集成完成了。
如果需要在加上nacos数据和sentinel控制台的数据修改同步,则需要再加上一个客户端回调端口和数据回写的实现。
sentinel在数据回写时会调用WritableDataSource 这个接口的实现。
/**
* 流控规则推送
* @return
*/
@Bean("flowRuleNacosWritableDataSource")
public NacosWritableDataSource<List<FlowRule>> flowRuleNacosWritableDataSource(){
if (!StringUtils.isEmpty(flowRuleDataId)){
if (StringUtils.isEmpty(flowRuleGroupId) && StringUtils.isEmpty(groupId)) {
throw new IllegalArgumentException("groupId is empty !");
}
final NacosWritableDataSource<List<FlowRule>> nacosWritableDataSource;
try {
nacosWritableDataSource = new NacosWritableDataSource<List<FlowRule>>(flowRuleDataId,flowRuleGroupId,nameSpaceId,address);
WritableDataSourceRegistry.registerFlowDataSource(nacosWritableDataSource);
return nacosWritableDataSource;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 熔断规则推送
* @return
*/
@Bean("degradeNacosWritableDataSource")
public NacosWritableDataSource<List<DegradeRule>> degradeNacosWritableDataSource(){
if (!StringUtils.isEmpty(degradeRuleDataId)){
if (StringUtils.isEmpty(degradeRuleGroupId) && StringUtils.isEmpty(groupId)) {
throw new IllegalArgumentException("groupId is empty !");
}
final NacosWritableDataSource<List<DegradeRule>> nacosWritableDataSource;
try {
nacosWritableDataSource = new NacosWritableDataSource<List<DegradeRule>>(degradeRuleDataId,
StringUtils.isEmpty(degradeRuleGroupId)?groupId:degradeRuleGroupId,
nameSpaceId,
address);
WritableDataSourceRegistry.registerDegradeDataSource(nacosWritableDataSource);
return nacosWritableDataSource;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
上面简单写了流控和熔断的规则回写实现。
最重要的是在启动的时候我们需要加上-Dcsp.sentinel.api.port=9092参数,这个端口会在服务启动的时候额外开一个端口用作控制台回调使用
上图中的ip端口就是在数据修改后会回调的服务ip