Sentinel Dashboard支持规则配置持久化至Nacos

简介: 目录前言一、Push模式原理二、Sentinel控制台改造支持配置持久化至Nacos1、拉取最新代码2、开始搬运代码(1) 调整点之修改NacosConfig类(2) 调整点之新增NacosConfigProperties类(3) 调整点之修改NacosConfigUtil类(4) DynamicRuleProvider和DynamicRulePublisher实现优化1) AbstractNacosProvider类2) AbstractNacosPublisher类3) FlowRuleNacosProvider类4) FlowRuleNacosPublisher

目录

前言

一、Push模式原理

二、Sentinel控制台改造支持配置持久化至Nacos

1、拉取最新代码

2、开始搬运代码

(1) 调整点之修改NacosConfig类

(2) 调整点之新增NacosConfigProperties类

(3) 调整点之修改NacosConfigUtil类

(4) DynamicRuleProvider和DynamicRulePublisher实现优化

1) AbstractNacosProvider类

2) AbstractNacosPublisher类

3) FlowRuleNacosProvider类

4) FlowRuleNacosPublisher类

3、修改Controller

(1) FlowControllerV2类

(2) DegradeControllerV2类

4、修改前端路由配置文件sidebar.html

5、Sentinel控制台application.properties

6、启动Sentinel控制台

三、Sentinel客户端接入Nacos数据源

1、Maven依赖

2、bootstrap.yaml

3、application.yml

四、Sentinel客户端测试用例

1、SentinelController

2、登录Sentinel控制台修改流控规则

3、登录Nacos控制台查看流控规则

4、请求示例

前言

Sentinel控制台规则管理和推送主要有3种方式:原始模式Pull模式Push模式,如果不做任何修改,默认使用的是原始模式

所谓原始模式就是Sentinel控制台通过相关API直接将规则推送至客户端并直接更新到内存中,下面是三种模式的对比。b0cbf7aba58d4aa7af87f00ae22ed254.png

原始模式规则配置由于是在内存中,重启就会消失。

因此在生产环境中Sentinel官方推荐我们使用Push模式实现动态规则配置和持久化,我们一般会依赖一些第三方中间件,如NacosApolloZookeeperRedis等来实现。

一、Push模式原理



Push模式的推送流程是:Sentinel控制台新增/修改配置持久化至配置中心(Nacos)Sentinel数据源监听配置中心最新配置Sentinel客户端从数据源中读取配置

整体流程图如下:c95643e790544fd09a9958a46247571d.png

更多内容请参考:在生产环境中使用Sentinel

二、Sentinel控制台改造支持配置持久化至Nacos



由于Sentinel控制台本身并不支持在前端界面修改规则配置后推送至第三方配置中心,因此我们需要对Sentinel Dashboard的代码进行修改。


控制台代码修改的思路参考:Sentinel控制台集群流控管理。


1、拉取最新代码

直接从Github上拉取sentinel-dashboard的代码即可,我拉取的版本是1.8.1。



2、开始搬运代码

拉下代码后,可以看到在test目录下,有关于Nacos规则推送的类,我们可以直接搬过去。

bf0d3e9228dc4572b25984e5b6acaf66.png

这里我自己其实做了一些代码优化和小调整,调整后的文件目录如下:50c8a092c53c48cead71e578b11677db.png

(1) 调整点之修改NacosConfig类

@Configuration
@EnableConfigurationProperties(NacosConfigProperties.class)
public class NacosConfig {
  @Autowired
  private NacosConfigProperties nacosConfigProperties;
  @Bean
  public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
    return JSON::toJSONString;
  }
  @Bean
  public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
    return s -> JSON.parseArray(s, FlowRuleEntity.class);
  }
  @Bean
  public Converter<List<DegradeRuleEntity>, String> degradeRuleEntityEncoder() {
    return JSON::toJSONString;
  }
  @Bean
  public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
    return s -> JSON.parseArray(s, DegradeRuleEntity.class);
  }
  @Bean
  public ConfigService nacosConfigService() throws Exception {
    Properties properties = new Properties();
    // 这里在创建ConfigService实例时加了Nacos实例地址和命名空间两个属性。
    properties.put(PropertyKeyConst.SERVER_ADDR, nacosConfigProperties.getServerAddr());
    properties.put(PropertyKeyConst.NAMESPACE, nacosConfigProperties.getNamespace());
    return ConfigFactory.createConfigService(properties);
  }
}

(2) 调整点之新增NacosConfigProperties类

@ConfigurationProperties(prefix = "sentinel.config.nacos")
public class NacosConfigProperties {
  /**
   * nacos服务器地址
   */
  private String serverAddr;
  /**
   * nacos命名空间
   */
  private String namespace;
  /**
   * 分组名
   */
  private String groupId = NacosConfigUtil.GROUP_ID;
  /**
   * 限流规则dataId后缀
   */
  private String flowRuleDataIdSuffix = NacosConfigUtil.FLOW_DATA_ID_POSTFIX;
  /**
   * 降级规则dataId后缀
   */
  private String degradeRuleDataIdSuffix = NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX;
  public String getServerAddr() {
    return serverAddr;
  }
  public void setServerAddr(String serverAddr) {
    this.serverAddr = serverAddr;
  }
  public String getNamespace() {
    return namespace;
  }
  public void setNamespace(String namespace) {
    this.namespace = namespace;
  }
  public String getGroupId() {
    return groupId;
  }
  public void setGroupId(String groupId) {
    this.groupId = groupId;
  }
  public String getFlowRuleDataIdSuffix() {
    return flowRuleDataIdSuffix;
  }
  public void setFlowRuleDataIdSuffix(String flowRuleDataIdSuffix) {
    this.flowRuleDataIdSuffix = flowRuleDataIdSuffix;
  }
  public String getDegradeRuleDataIdSuffix() {
    return degradeRuleDataIdSuffix;
  }
  public void setDegradeRuleDataIdSuffix(String degradeRuleDataIdSuffix) {
    this.degradeRuleDataIdSuffix = degradeRuleDataIdSuffix;
  }
}


(3) 调整点之修改NacosConfigUtil类

public final class NacosConfigUtil {
  public static final String GROUP_ID = "SENTINEL_GROUP";
  public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";
  public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-rules";
  public static final String SYSTEM_FULE_DATA_ID_POSTFIX = "-system-rules";
  public static final String AUTHORITY_DATA_ID_POSTFIX = "-authority-rules";
  public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-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() {
  }
}

这里我用模板方法模式优化了一下代码,新增了AbstractNacosProvider和AbstractNacosPublisher两个类。


1) AbstractNacosProvider类


public abstract class AbstractNacosProvider<T> implements DynamicRuleProvider<List<T>> {
  private static final long timeoutInMills = 3000;
  @Autowired
  private NacosConfigProperties nacosConfigProperties;
  @Autowired
  private ConfigService configService;
  @Autowired
  private Converter<String, List<T>> converter;
  @Override
  public List<T> getRules(String appName) throws Exception {
    String dataId = appName + getDataIdSuffix();
    String groupId = nacosConfigProperties.getGroupId();
    String rules = configService.getConfig(dataId, groupId, timeoutInMills);
    return StringUtil.isEmpty(rules) ? Collections.emptyList() : converter.convert(rules);
  }
  protected NacosConfigProperties getNacosConfigProperties() {
    return nacosConfigProperties;
  }
  protected abstract String getDataIdSuffix();
}

2) AbstractNacosPublisher类

public abstract class AbstractNacosPublisher<T> implements DynamicRulePublisher<List<T>> {
  @Autowired
  private NacosConfigProperties nacosConfigProperties;
  @Autowired
  private ConfigService configService;
  @Autowired
  private Converter<List<T>, String> converter;
  @Override
  public void publish(String app, List<T> rules) throws Exception {
    AssertUtil.notEmpty(app, "app name cannot be empty");
    if (CollectionUtils.isEmpty(rules)) {
      return;
    }
    String dataId = app + getDataIdSuffix();
    String groupId = nacosConfigProperties.getGroupId();
    configService.publishConfig(dataId, groupId, converter.convert(rules));
  }
  protected NacosConfigProperties getNacosConfigProperties() {
    return nacosConfigProperties;
  }
  protected abstract String getDataIdSuffix();
}

3) FlowRuleNacosProvider类

@Component("flowRuleNacosProvider")
public class FlowRuleNacosProvider extends AbstractNacosProvider<FlowRuleEntity> {
  @Override
  protected String getDataIdSuffix() {
    return super.getNacosConfigProperties().getFlowRuleDataIdSuffix();
  }
}

4) FlowRuleNacosPublisher类

@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher extends AbstractNacosPublisher<FlowRuleEntity> {
  @Override
  protected String getDataIdSuffix() {
    return super.getNacosConfigProperties().getFlowRuleDataIdSuffix();
  }
}

3、修改Controller

(1) FlowControllerV2类

需要注意的是,FlowControllerV2类主要用于集群流控相关的规则配置读取和发布,而FlowControllerV1类用于单个应用维度流控的规则配置和发布。


这个类这里我们把动态规则获取和发布相关实现类改成了我们自己实现的基于Nacos的实现,如下:2b8a9e79160c49109d5eadf8853ac74a.png


备注:其它修改处,如从Nacos中读取流控规则配置,发布流控规则配置到Nacos的代码示例,请参考代码:FlowControllerV2。

(2) DegradeControllerV2类

降级规则配置读取和发布控制器的修改和FlowControllerV2基本差不多,只不过降级是针对单个应用。

2b8a9e79160c49109d5eadf8853ac74a.png



备注:这里我新复制了一个DegradeControllerV2类,注意把DegradeController类上的@RestController注解给干掉。其它细节修改请参考:DegradeControllerV2。

4、修改前端路由配置文件sidebar.html

之前这里的流控规则的路由是:dashboard.flowV1,也就是路由到FlowController。现在我们把修改为dashboard.flow,也就是路由到FlowControllerV2。

04798b80611d448b8159583f6af68e86.png

备注:到这里sentinel控制台的代码修改就差不多了,至于其它规则Controller的修改,如:热点规则、系统规则、授权规则等,可以参考上面的DegradeControllerV2类。

5、Sentinel控制台application.properties

新增Nacos数据源相关的自定义配置,我们在NacosConfigProperties类中有定义过。


# nacos server address
sentinel.config.nacos.server-addr=localhost:8848
# nacos namespace to use
sentinel.config.nacos.namespace=d3a61a32-1c74-4fc6-a9f2-1cf18675c4ee

6、启动Sentinel控制台a89a06a0b5c748eba1a83172e35349b4.png

备注:用户名和密码都是sentinel

三、Sentinel客户端接入Nacos数据源


1、Maven依赖

<dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--动态扩展之数据源支持-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>${sentinel-datasouce-nacos.version}</version>
        </dependency>
</dependencies>

2、bootstrap.yaml

server:
  port: 9010
spring:
  application:
    name: sentinel-client


3、application.yml

这里我们流控和降级相关的规则都是从Nacos中读取,如下:

spring:
  cloud:
    sentinel:
      datasource:
        flow-ds:
          nacos:
            server-addr: localhost:8848
            namespace: d3a61a32-1c74-4fc6-a9f2-1cf18675c4ee
            data-id: ${spring.application.name}-flow-rules
            group-id: SENTINEL_GROUP
            data-type: json
            rule-type: flow
        degrade-ds:
          nacos:
            server-addr: localhost:8848
            namespace: d3a61a32-1c74-4fc6-a9f2-1cf18675c4ee
            data-id: ${spring.application.name}-degrade-rules
            group-id: SENTINEL_GROUP
            data-type: json
            rule-type: degrade
      transport:
        port: 8719 #与sentinel dashboard的通信端口,会启动一个http server,供dashboard调用
        dashboard: localhost:9999 #dashboard地址和端口

更多内容请参考:Sentinel集成Spring Cloud Alibaba动态数据源支持

四、Sentinel客户端测试用例


1、SentinelController

@RestController
public class SentinelController {
  @GetMapping("/order")
  @SentinelResource(value = ResourceDefConst.ORDER_INFO, blockHandler = "exceptionHandler", fallback = "fallback")
  public String queryOrderInfo(long orderId) {
    Random random = new Random();
    int timeout = random.nextInt(150);
    LockSupport.parkNanos(timeout * 1000 * 1000);
    System.out.println(String.format("调用时间为:%d", timeout));
    return String.format("订单信息:%d", orderId);
  }
  /**
   * 若blockHandler和fallback都进行了配置,则被限流降级时抛出BlockException时只会进入blockHandler逻辑
   * @param orderId
   * @param e
   * @return
   */
  public String exceptionHandler(long orderId, BlockException e) {
    e.printStackTrace();
    return "服务降级啦!";
  }
  public String fallback(long orderId, Throwable t) {
    t.printStackTrace();
    return "服务异常啦!";
  }
}

2、登录Sentinel控制台修改流控规则

这里我们修改了资源名为order_info的流控规则为基于QPS的限流且阈值为2。a250aeacbeeb4ce58bc863c3d76f77f9.png

3、登录Nacos控制台查看流控规则

在上一步我们已经在Sentinel控制台修改了集群流控相关的规则,我们登录Nacos控制台看看配置是否已经持久化到了Nacos上2bbe48c027d74e33a38cdc206a9ffe3b.png

备注:可以看到Sentinel控制台的修改确实同步到了Nacos上。

4、请求示例

当我们访问http://localhost:9010/order?orderId=1,可以看到当QPS超过2时会触发FlowException,说明我们的流控规则修改是生效的。13e4fde9c6664e099636b95cf0923059.png

备注:关于降级规则的测试同样可以在Sentinel控制台上进行操作。

相关文章
|
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、强化数据库安全、启用访问控制、监控和审计等步骤,帮助开发者确保服务的安全运行。
23 3
|
30天前
|
负载均衡 算法 Java
蚂蚁面试:Nacos、Sentinel了解吗?Springcloud 核心底层原理,你知道多少?
40岁老架构师尼恩分享了关于SpringCloud核心组件的底层原理,特别是针对蚂蚁集团面试中常见的面试题进行了详细解析。内容涵盖了Nacos注册中心的AP/CP模式、Distro和Raft分布式协议、Sentinel的高可用组件、负载均衡组件的实现原理等。尼恩强调了系统化学习的重要性,推荐了《尼恩Java面试宝典PDF》等资料,帮助读者更好地准备面试,提高技术实力,最终实现“offer自由”。更多技术资料和指导,可关注公众号【技术自由圈】获取。
蚂蚁面试:Nacos、Sentinel了解吗?Springcloud 核心底层原理,你知道多少?
|
19天前
|
SQL 关系型数据库 数据库连接
"Nacos 2.1.0版本数据库配置写入难题破解攻略:一步步教你排查连接、权限和配置问题,重启服务轻松解决!"
【10月更文挑战第23天】在使用Nacos 2.1.0版本时,可能会遇到无法将配置信息写入数据库的问题。本文将引导你逐步解决这一问题,包括检查数据库连接、用户权限、Nacos配置文件,并提供示例代码和详细步骤。通过这些方法,你可以有效解决配置写入失败的问题。
43 0
|
2月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
4月前
|
Java Nacos 数据库
使用 nacos 搭建注册中心及配置中心
使用 nacos 搭建注册中心及配置中心
100 5
|
4月前
|
NoSQL Java Nacos
SpringCloud集成Seata并使用Nacos做注册中心与配置中心
SpringCloud集成Seata并使用Nacos做注册中心与配置中心
137 3