让sentinel-dashboard的流控配置持久化到nacos

简介: 让sentinel-dashboard的流控配置持久化到nacos


官网 git: https://github.com/alibaba/Sentinel

微服务可以将流控配置放在nacos中,但dashboard修改的规则不能持久化。

本文将dashboard中的修改同步到nacos中,dashboard监控流控仍然从微服务客户端读取。

微服务客户端重启后会从nacos中读取数据,实现持久化。

主要思路: dashboard修改配置的时候,将数据发布到nacos中。注意dashboard中的是xxRuleEntity,而客户端读取nacos的是xxRule.

master分支 目前为sentinel-1.8.0为例

下载源码,idea打开。

找到sentinel-dashboard这个项目

在该项目下的pom.xml文件中找到:

  <!-- for Nacos rule publisher sample -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
        <scope>test</scope>
    </dependency>

将test注释掉。

展开test->java->com.alibaba.csp.sentinel.dashboard->rule->nacos

复制到src->java->com.alibaba.csp.sentinel.dashboard

  1. 主要文件

NacosCofig 服务配置 及convert


@Configuration
public class NacosConfig {

@Value("${sentinel.datasource.nacos.server-addr:localhost:8848}")
private String serverAddr;

@Value("${sentinel.datasource.nacos.enable:false}")
private boolean enable;

@Bean
public FlowRuleConvert flowRuleEntityEncoder() {
    return new FlowRuleConvert();
}

@Bean
public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
    return s -> JSON.parseArray(s, FlowRuleEntity.class);
}

@Bean
public ParamFlowRuleConvert paramFlowRuleEntityEncoder() {
    return new ParamFlowRuleConvert();
}

@Bean
public Converter<String, List<ParamFlowRuleEntity>> paramFlowRuleEntityDecoder() {
    return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
}



@Bean
public DegradeRuleConvert degradeRuleEntityEncoder() {
    return new DegradeRuleConvert();
}

@Bean
public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
    return s -> JSON.parseArray(s, DegradeRuleEntity.class);
}

@Bean
public ConfigService nacosConfigService() throws Exception {
    return ConfigFactory.createConfigService(serverAddr);
}


public boolean isEnable() {
    return enable;
}

public void setEnable(boolean enable) {
    this.enable = enable;
}

}

默认配置 NacosConfigUtil

注意 GROUP_ID 、xx_DATA_ID_POSTFIX 需要微服务客户端的一致

public final class NacosConfigUtil {

// public static final String GROUP_ID = "SENTINEL_GROUP";

public static final String GROUP_ID = "DEFAULT_GROUP";

public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";
public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules";
public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-rules";
public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map";

/**
 * cc for `cluster-client`
 */
public static final String CLIENT_CONFIG_DATA_ID_POSTFIX = "-cc-config";
/**
 * cs for `cluster-server`
 */
public static final String SERVER_TRANSPORT_CONFIG_DATA_ID_POSTFIX = "-cs-transport-config";
public static final String SERVER_FLOW_CONFIG_DATA_ID_POSTFIX = "-cs-flow-config";
public static final String SERVER_NAMESPACE_SET_DATA_ID_POSTFIX = "-cs-namespace-set";

private NacosConfigUtil() {}

}

FlowRuleNacosPublisher 规则发布

@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List> {

@Autowired
private ConfigService configService;
@Autowired
private FlowRuleConvert converter;

@Override
public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
    AssertUtil.notEmpty(app, "app name cannot be empty");
    if (rules == null) {
        return;
    }
    boolean success = configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
        NacosConfigUtil.GROUP_ID, converter.convert(rules));
    if(!success){
        throw new RuntimeException("publish to nacos fail");
    }
}

}
ParamFlowRuleNacosPublisher

@Component("paramFlowRuleNacosPublisher")
public class ParamFlowRuleNacosPublisher implements DynamicRulePublisher<List> {

@Autowired
private ConfigService configService;
@Autowired
private ParamFlowRuleConvert converter;

@Override
public void publish(String app, List<ParamFlowRuleEntity> rules) throws Exception {
    AssertUtil.notEmpty(app, "app name cannot be empty");
    if (rules == null) {
        return;
    }
    boolean success = configService.publishConfig(app + NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX,
        NacosConfigUtil.GROUP_ID, converter.convert(rules));
    if(!success){
        throw new RuntimeException("publish to nacos fail");
    }
}

}

DegradeRuleNacosPublisher

@Component("degradeRuleNacosPublisher")
public class DegradeRuleNacosPublisher implements DynamicRulePublisher<List> {

@Autowired
private ConfigService configService;
@Autowired
private DegradeRuleConvert converter;

@Override
public void publish(String app, List<DegradeRuleEntity> rules) throws Exception {
    AssertUtil.notEmpty(app, "app name cannot be empty");
    if (rules == null) {
        return;
    }
    boolean success = configService.publishConfig(app + NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX,
        NacosConfigUtil.GROUP_ID, converter.convert(rules));

    if(!success){
        throw new RuntimeException("publish to nacos fail");
    }
}

}

  1. 转换类

FlowRuleConvert

public class FlowRuleConvert implements Converter<List, String> {

@Override
public String convert(List<FlowRuleEntity> flowRuleEntities) {
    if(flowRuleEntities==null){
        return null;
    }
    List<FlowRule> flowRules = new ArrayList<>();
    for (FlowRuleEntity entity : flowRuleEntities) {
        FlowRule rule = new FlowRule();
        rule.setLimitApp(entity.getLimitApp());
        rule.setResource(entity.getResource());
        if(entity.getGmtCreate()!=null){
            rule.setGrade(entity.getGrade());
        }
        if(entity.getCount()!=null){
            rule.setCount(entity.getCount());
        }
        if(entity.getStrategy()!=null){
            rule.setStrategy(entity.getStrategy());
        }
        rule.setRefResource(entity.getRefResource());
        if(entity.getControlBehavior()!=null){
            rule.setControlBehavior(entity.getControlBehavior());
        }
        if(entity.getWarmUpPeriodSec()!=null){
            rule.setWarmUpPeriodSec(entity.getWarmUpPeriodSec());
        }
        if(entity.getMaxQueueingTimeMs()!=null){
            rule.setMaxQueueingTimeMs(entity.getMaxQueueingTimeMs());
        }
        rule.setClusterMode(entity.isClusterMode());
        rule.setClusterConfig(entity.getClusterConfig());

        flowRules.add(rule);
    }
    return JSON.toJSONString(flowRules,true);
}

}

ParamFlowRuleConvert

DegradeRuleConvert

@Autowired
private NacosConfig nacosConfig;

@Autowired
private FlowRuleNacosPublisher flowRuleNacosPublisher;

/ 修改publish /
private CompletableFuture publishRules(String app, String ip, Integer port) throws Exception {

List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
if(nacosConfig.isEnable()){
    flowRuleNacosPublisher.publish(app,rules);
}
return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);

}

ParamFlowRuleController

@Autowired
private NacosConfig nacosConfig;

@Autowired
private ParamFlowRuleNacosPublisher paramFlowRuleNacosPublisher;

private CompletableFuture publishRules(String app, String ip, Integer port) throws Exception {

List<ParamFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
if(nacosConfig.isEnable()){
    paramFlowRuleNacosPublisher.publish(app,rules);
}
return sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules);

}

DegradeController

@Autowired
private NacosConfig nacosConfig;

@Autowired
private DegradeRuleNacosPublisher degradeRuleNacosPublisher;

private boolean publishRules(String app, String ip, Integer port) {

List<DegradeRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
if(nacosConfig.isEnable()){
    try {
        degradeRuleNacosPublisher.publish(app,rules);
    } catch (Exception e) {
        logger.error("publishRules failed. ",e);
        return false;
    }
}
return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);

}

  1. 配置文件

nacos 配置开关 默认false

sentinel.datasource.nacos.enable=true

nacos 地址 默认 localhost:8848

sentinel.datasource.nacos.server-addr=localhost:8848
5 微服务端示例

配置文件

server:
port: 8081
spring:
application:

name: sentinel-spring-cloud-nacos

cloud:

sentinel:
  transport:
    dashboard: localhost:8080
  eager: false
  # sentinel nacos
  datasource:
    ds-flow:
      nacos:
        server-addr: 192.168.116.128:8848
        dataId: ${spring.application.name}-flow-rules
        groupId: DEFAULT_GROUP
        dataType: json
        rule-type: flow
    ds-param:
      nacos:
        server-addr: 192.168.116.128:8848
        dataId: ${spring.application.name}-param-rules
        groupId: DEFAULT_GROUP
        dataType: json
        rule-type: param-flow
    ds-degrade:
      nacos:
        server-addr: 192.168.116.128:8848
        dataId: ${spring.application.name}-degrade-rules
        groupId: DEFAULT_GROUP
        dataType: json
        rule-type: degrade

SentinelResource

@RestController
@RequestMapping("/api/sentinel")
public class SentinelDemoController {

@SentinelResource(value = "helloSentinel",blockHandler = "blockHandler",blockHandlerClass = SentinelBlockUtil.class )
@GetMapping("/helloSentinel")
public Object helloSentinel(){
    return "hello sentinel. "+System.currentTimeMillis();
}


@SentinelResource(value = "helloSentinelParam",blockHandler = "oneParamBlockHandler",blockHandlerClass = SentinelBlockUtil.class)
@GetMapping("/helloSentinelParam")
public Object helloSentinelParam(String userId){
    String data = "hello helloSentinelParam. userId:"+userId+"  "+System.currentTimeMillis();
    return data;
}

}
源码:https://github.com/lvzhyt/Sentinel/tree/dashboard-nacos

dashboard-nacos 分支 sentinel-dashboard

微服务客户端示例 sentinel-demo-spring-cloud-nacos

相关文章
|
11天前
|
负载均衡 应用服务中间件 Nacos
Nacos配置中心
Nacos配置中心
40 1
Nacos配置中心
|
7天前
|
监控 Java 测试技术
Nacos 配置中心变更利器:自定义标签灰度
本文是对 MSE Nacos 应用自定义标签灰度的功能介绍,欢迎大家升级版本进行试用。
|
10天前
|
网络安全 Nacos 开发者
Nacos作为流行的微服务注册与配置中心,“节点提示暂时不可用”是常见的问题之一
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。然而,“节点提示暂时不可用”是常见的问题之一。本文将探讨该问题的原因及解决方案,帮助开发者快速定位并解决问题,确保服务的正常运行。通过检查服务实例状态、网络连接、Nacos配置、调整健康检查策略等步骤,可以有效解决这一问题。
22 4
|
10天前
|
Java 网络安全 Nacos
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。然而,实际使用中常遇到“客户端不发送心跳检测”的问题。本文深入探讨该问题的原因及解决方案,帮助开发者快速定位并解决问题,确保服务正常运行。通过检查客户端配置、网络连接、日志、版本兼容性、心跳策略、注册状态、重启应用和环境变量等步骤,系统地排查和解决这一问题。
26 3
|
10天前
|
安全 Nacos 数据库
Nacos是一款流行的微服务注册与配置中心,但直接暴露在公网中可能导致非法访问和数据库篡改
Nacos是一款流行的微服务注册与配置中心,但直接暴露在公网中可能导致非法访问和数据库篡改。本文详细探讨了这一问题的原因及解决方案,包括限制公网访问、使用HTTPS、强化数据库安全、启用访问控制、监控和审计等步骤,帮助开发者确保服务的安全运行。
24 3
|
19天前
|
SQL 关系型数据库 数据库连接
"Nacos 2.1.0版本数据库配置写入难题破解攻略:一步步教你排查连接、权限和配置问题,重启服务轻松解决!"
【10月更文挑战第23天】在使用Nacos 2.1.0版本时,可能会遇到无法将配置信息写入数据库的问题。本文将引导你逐步解决这一问题,包括检查数据库连接、用户权限、Nacos配置文件,并提供示例代码和详细步骤。通过这些方法,你可以有效解决配置写入失败的问题。
44 0
|
2月前
|
监控 Java API
谷粒商城笔记+踩坑(25)——整合Sentinel实现流控和熔断降级
先简单介绍熔断、降级等核心概念,然后阐述SpringBoot整合Sentinel的实现方式,最后介绍Sentinel在本项目中的应用。
谷粒商城笔记+踩坑(25)——整合Sentinel实现流控和熔断降级
|
4月前
|
Java Nacos 数据库
使用 nacos 搭建注册中心及配置中心
使用 nacos 搭建注册中心及配置中心
100 5
|
4月前
|
NoSQL Java Nacos
SpringCloud集成Seata并使用Nacos做注册中心与配置中心
SpringCloud集成Seata并使用Nacos做注册中心与配置中心
137 3
|
2月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway