不改一行源码,实现sentinel控制台跟consul的的双向数据持久化

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;
            }
        }
    }

}

测试验证无误

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Sentinel 控制台是一个基于 Spring Cloud 的应用,它提供了一个可视化的界面来管理和监控 Sentinel 的流控规则、降级规则、系统规则等。而 Nacos 是一个开源的注册中心和配置中心,它提供了服务注册、配置管理和服务发现等功能。将 Sentinel 控制台持久化到 Nacos 可以实现Sentinel 控制台配置的动态管理和版本控制。 将 Sentinel 控制台持久化到 Nacos,需要进行以下步骤: 1. 在 Nacos 控制台中创建一个命名空间和配置集,用来保存 Sentinel 控制台的配置信息。 2. 在 Sentinel 控制台的 application.properties 配置文件中,添加以下配置: ``` # 配置 Nacos 的服务地址和命名空间 spring.cloud.nacos.config.server-addr=<Nacos 服务地址> spring.cloud.nacos.config.namespace=<Nacos 命名空间> # 配置 Sentinel 控制台的配置信息 spring.cloud.sentinel.transport.dashboard=localhost:8080 management.endpoints.web.exposure.include=sentinel spring.cloud.sentinel.eager=true ``` 3. 在 Sentinel 控制台启动后,访问 http://localhost:8080/nacos/config 会自动将 Sentinel 控制台的配置信息保存到 Nacos 中。 4. 在 Nacos 控制台中修改 Sentinel 控制台的配置信息,可以实现Sentinel 控制台配置的动态管理和版本控制。 需要注意的是,将 Sentinel 控制台持久化到 Nacos 需要使用 Sentinel 控制台的 1.8.0 版本及以上,同时需要安装 Nacos 的配置中心服务。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值