springcloud-alibaba-sentinel(6)sentinel控制台规则操作持久化至Nacos (二)

前言

书接上文

springcloud-alibaba-sentinel(5)sentinel规则持久化至Nacos (一)

我们实现了Nacos编写Sentinel配置规则然后持久化,sentinel-dashboard控制台可以显示

image-20220419112055015

但仍存在一个问题,那就是sentinel-dashboard编写的规则却没有保存到Nacos,导致sentinel客户端(我们的微服务)重启之后,我们的规则全部丢失

那么我们能不能实现 Nacos>sentinel 与 sentinel>nacos双向操作持久化呢?

image-20220419181152989

为了解决这个问题,我们需要Down下Sentinel源码来看看究竟

Sentinel源码下载与编译

下载

源码git地址:https://github.com/alibaba/Sentinel/releases

选择ZIP下载解压后,拖入IDEA

image-20220419113636507

项目结构展示

从源码中可以看到,sentinel的项目结构为单体多模块

image-20220419114404610

image-20220419134029450

项目编译运行

在项目根目录下打开Terminal执行命令

mvn clean package -Dmaven.test.skip=true

image-20220419135816287

源码查看

流控规则控制器完全限定名为:

com.alibaba.csp.sentinel.dashboard.controller.FlowControllerV1

新增流控源码

image-20220419181621448

发现最终是保存到了内存中

image-20220419140138335

因为控制台的一切规则操作,默认都是保存在内存中的,所以其没有持久化到Nacos,以及Sentinel客户端或者DashBoard重启后,规则丢失了!

源码运行

将application.properties修改为YMl配置

auth:
  filter:
    exclude-url-suffixes: htm,html,js,css,map,ico,ttf,woff,png
    exclude-urls: /,/auth/login,/auth/logout,/registry/machine,/version
  password: sentinel
  username: sentinel
logging:
  file:
    name: ${user.home}/logs/csp/sentinel-dashboard.log
  level:
    org:
      springframework:
        web: INFO
  pattern:
    file: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n'
sentinel:
  dashboard:
    version: '@project.version@'
server:
  servlet:
    encoding:
      charset: UTF-8
      enabled: true
      force: true
    session:
      cookie:
        name: sentinel_dashboard_cookie
  port: 8080

选择sentinel-dashboard模块的DashboardApplication 点击启动

image-20220419142719057

访问URL即可完成登陆

image-20220419181725095

Sentinel源码改造

目录

webapp/resources/app/scripts/directives/sidebar/sidebar.html

是sentinel前端页面

image-20220420095440708

image-20220419141238011

目录

webapp/resources/app/scripts/app.js

是sentinel前端页面访问后端控制器的JS配置,里面编写了哪个页面访问后端URL地址


下边我将以流控规则持久化为示例演示

ps: 因为源码中,流控规则持久化,作者已经为我们打了个样,我们只需要按照其逻辑,然后将底层实现修改为Nacos,即可实现控制台操作流控规则持久化到Nacos了

Sentinel—Dashboard控制台实现持久化原理

我们主要是改写Sentinel-dashboard后端接口,使用我们自定义的Nacos数据源,与Nacos进行交互,将我们新增 修改 删除的配置 同时推送到Nacos中

幸运的是,一切都是有轮子的,我们上边引入的sentinel-datasource-nacos已经是有了相应的接口,我们只需要实现它即可

image-20220419150933409

Sentinel 开发者为Nacos持久化数据打的样

Test目录下,已经有了相应的示例,如何连接与配置Nacos,如何推送Nacos

NacosConfig :nacos相关配置

FlowRuleNacosProvider :负责从Nacos读取配置

FlowRuleNacosPublisher :负责将Sentinel-dashboard配置推送至Nacos服务端

image-20220419151604785

修改流控前端页面

因为项目中流控有V1 V2 两个控制器,V2版本是作者打的样,因此我们需要修改前端访问后端的逻辑 由请求V1 修改为请求V2

image-20220419143642755

修改为

          <li ui-sref-active="active" ng-if="!entry.isGateway">
            <a ui-sref="dashboard.flow({app: entry.app})">
              <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>
          </li>

核心修改是 dashboard.flowV1 更改为dashboard.flow 去掉了V1后缀

我们可以Ctrl + 鼠标左键 点击去查看,无V1 后缀的实际是请求的V2控制器

image-20220419143954002

开启Nacos数据源支持

sentinel-dashboard中,默认引入了Nacos数据源,但其作用范围为test,我们需要修改一下

image-20220419144254490

Nacos配置

我们需要根据自己的实际情况配置Nacos相关属性,比如是账号密码,服务地址 命名空间等等

详细的配置项支持请查看源码:(其是一个常量类,里边定义了Nacos的一些可支持配置)

com.alibaba.nacos.api.PropertyKeyConst
package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

/**
 * @author lei
 * @create 2022-04-13 13:57
 * @desc nacos配置
 **/
@Configuration
public class NacosConfig {

    @Bean
    public ConfigService nacosConfigService() throws Exception {
        Properties properties = new Properties();
        // 我这里指明了Nacos地址
        properties.put(PropertyKeyConst.SERVER_ADDR, "http://10.50.40.116:8765");
        // 指明了命名空间
        properties.put(PropertyKeyConst.NAMESPACE, "c0fed0b5-46a6-44b9-b850-44c2ae0d7fe7");
        return ConfigFactory.createConfigService(properties);
    }

}

image-20220419152236949

需要注意的是,如果指定的命名空间需要在Nacos中先进行创建

公共Nacos推送拉取实现

我们根据开发者为我们打的样,对Nacos读取配置,以及推送配置两个动作做一个抽取,这样的话,其他任何规则需要持久化Nacos都只需要调用公共方法即可

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.RuleEntity;
import com.alibaba.csp.sentinel.slots.block.Rule;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lei
 * @create 2022-04-13 15:17
 * @desc nacos操作类
 **/
@Service
public class NacosSupport {

    private final ConfigService configService;

    private static final Logger logger = LoggerFactory.getLogger(NacosSupport.class);

    private NacosSupport(ConfigService configService) {
        this.configService = configService;
    }

    public static final String GROUP_ID = "DEFAULT_GROUP";
    public static final String RULE_PREFIX = "-sentinel";

    public static final String FLOW_DATA_ID_POSTFIX = RULE_PREFIX + "-rule-flow";
    public static final String DEGRADE_DATA_ID_POSTFIX = RULE_PREFIX + "-rule-degrade";
    public static final String SYSTEM_DATA_ID_POSTFIX = RULE_PREFIX + "-rule-system";
    public static final String PARAM_FLOW_DATA_ID_POSTFIX = RULE_PREFIX + "-rule-param-flow";
    public static final String AUTHORITY_DATA_ID_POSTFIX = RULE_PREFIX + "-rule-authority";
    public static final String DASHBOARD_POSTFIX = "-dashboard";
    public static final String CLUSTER_MAP_DATA_ID_POSTFIX = RULE_PREFIX + "-cluster-map";

    public static final String TYPE = "json";


    /**
     * 将规则序列化成JSON文本,存储到Nacos-server中 (nacos持久化的数据库,可能是内存,可能是DB,一切看Nacos的持久化配置是否开启Mysql存储)
     *
     * @param app     应用名称
     * @param postfix 规则后缀
     * @param rules   规则对象
     * @throws NacosException 异常
     */
    public <T> void pushRule(String app, String postfix, List<T> rules) throws NacosException {
        if (StringUtil.isBlank(app)) {
            throw new RuntimeException("位置APP-NAME");  
        }
        if (rules == null) {
            return;
        }
        List<Rule> ruleForApp = rules.stream()
                .map(rule -> {
                    RuleEntity rule1 = (RuleEntity) rule;
                    System.out.println("RuleEntity " + rule1);
                    Rule rule2 = rule1.toRule();
                    System.out.println("Rule " + rule2);
                    return rule2;
                })
                .collect(Collectors.toList());

        // 规则消息推送至nacos
        String dataId = genDataId(app, postfix);
        configService.publishConfig(dataId, NacosSupport.GROUP_ID, JSON.toJSONString(ruleForApp), TYPE);

    }

    /**
     * 从Nacos server中查询响应规则,并将其反序列化成对应Rule实体
     *
     * @param appName 应用名称
     * @param postfix 规则后缀
     * @param clazz   类
     * @param <T>     泛型
     * @return 规则对象列表
     * @throws NacosException 异常
     */
    public <T> List<T> getRule(String appName, String postfix, Class<T> clazz) throws NacosException {
        String rules = configService.getConfig(genDataId(appName, postfix), NacosSupport.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return JSON.parseArray(rules, clazz);
    }

    private static String genDataId(String appName, String postfix) {
        return appName + postfix;
    }
}

流控规则生产者

从nacos拉取规则

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author lei
 * @create 2022-04-13 14:18
 * @desc 流控生产者
 **/
@Component("flowRuleNacosProvider")
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {

    private final NacosSupport nacosSupport;

    public FlowRuleNacosProvider(NacosSupport nacosSupport) {
        this.nacosSupport = nacosSupport;
    }

    @Override
    public List<FlowRuleEntity> getRules(String appName) throws Exception {
       return nacosSupport.getRule(appName, NacosSupport.FLOW_DATA_ID_POSTFIX, FlowRuleEntity.class);
    }

}

流控规则推送者

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author lei
 * @create 2022-04-13 14:20
 * @desc 流控规则推送者
 **/
@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {

    private final NacosSupport nacosSupport;

    public FlowRuleNacosPublisher(NacosSupport nacosSupport) {
        this.nacosSupport = nacosSupport;
    }

    @Override
    public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
        nacosSupport.pushRule(app, NacosSupport.FLOW_DATA_ID_POSTFIX, rules);
    }
}

修改流控规则控制器

主要是替换规则生产与推送者为我们自己定义的Nacos流控相关服务,其他无需改动

image-20220419171612740

– – – – – – – – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – – – ---- – – –

以上便是Sentinel-Dashboard规则持久化的全部改造,其他规则可以参照上方逻辑,继续修改,抓住修改核心(nacos的流控生产与推送者)

比如我们的熔断规则修改

熔断规则修改

由于熔断规则前端所用JS 没有像限流一样分为V1 V2,因此无需改动前端页面,只需要实现自己的Nacos数据推送者以及生产者即可

image-20220419173609159

修改控制器

源码代码中使用的都是基于内存操作的数据

image-20220419173824755

我们需要替换为自己的Nacos相关实现

image-20220419173951369

改造结果展示

开始无任何配置

image-20220419174126912

Sentinel-dashboard页面操作规则配置

我们期望的是 Sentinel-dashboard页面操作后,数据能同步到Nacos中

image-20220419174316601

sentinel源码中打印了我们的信息

image-20220419174342374

Nacos页面查看

image-20220419174448484

image-20220419174525066

Nacos页面操作规则配置

我们期望的是Nacos页面修改配置规则后,Sentinel-Dashboard页面能够接受到该配置

修改流控阈值为2

image-20220419180601339控制台页面查看

image-20220419180630128

sentinel 服务重启或者我们的微服务app-base-center重启后,流控规则依然存在

到此…sentinel源码就修改完毕了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值