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控制台上进行操作。

相关文章
|
6天前
|
SQL 关系型数据库 数据库连接
"Nacos 2.1.0版本数据库配置写入难题破解攻略:一步步教你排查连接、权限和配置问题,重启服务轻松解决!"
【10月更文挑战第23天】在使用Nacos 2.1.0版本时,可能会遇到无法将配置信息写入数据库的问题。本文将引导你逐步解决这一问题,包括检查数据库连接、用户权限、Nacos配置文件,并提供示例代码和详细步骤。通过这些方法,你可以有效解决配置写入失败的问题。
16 0
|
2月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
3月前
|
安全 Nacos 数据安全/隐私保护
升级指南:从Nacos 1.3.0 到 2.3.0,并兼容 Seata 的鉴权配置
本文详细介绍了如何在微服务环境下从 Nacos 1.3.0 升级到 2.3.0,并确保 Seata 各版本的兼容性。作者小米分享了升级过程中的关键步骤,包括备份配置、更新鉴权信息及验证测试等,并解答了常见问题。通过这些步骤,可以帮助读者顺利完成升级并提高系统的安全性与一致性。
110 8
升级指南:从Nacos 1.3.0 到 2.3.0,并兼容 Seata 的鉴权配置
|
3月前
|
运维 Java Nacos
Spring Cloud应用框架:Nacos作为服务注册中心和配置中心
Spring Cloud应用框架:Nacos作为服务注册中心和配置中心
|
3月前
|
缓存 Cloud Native Java
【紧急救援】Nacos配置上线后失效?手把手教你如何轻松搞定命名空间修改难题!
【8月更文挑战第15天】Nacos是关键的云原生服务管理平台,用于动态服务发现与配置管理。但在使用其管理微服务配置时,可能会遇到命名空间内的配置更新后不生效的问题。本文探讨此问题并提供解决方案。首先需确认Nacos服务器运行正常及客户端正确连接。接着检查客户端缓存配置,可通过禁用缓存或缩短缓存间隔来即时更新配置。例如,在Spring Cloud Alibaba Nacos配置中心中启用自动刷新功能,并设置每5秒拉取新配置。同时,对于新增配置项,需重启客户端应用。还需检查Nacos服务器日志排除异常,并考虑升级Nacos版本解决兼容性问题。通过这些步骤,通常可有效解决配置不生效的难题。
170 0
|
3月前
|
安全 Nacos 数据库
【技术安全大揭秘】Nacos暴露公网后被非法访问?!6大安全加固秘籍,手把手教你如何保护数据库免遭恶意篡改,打造坚不可摧的微服务注册与配置中心!从限制公网访问到启用访问控制,全方位解析如何构建安全防护体系,让您从此告别数据安全风险!
【8月更文挑战第15天】Nacos是一款广受好评的微服务注册与配置中心,但其公网暴露可能引发数据库被非法访问甚至篡改的安全隐患。本文剖析此问题并提供解决方案,包括限制公网访问、启用HTTPS、加强数据库安全、配置访问控制及监控等,帮助开发者确保服务安全稳定运行。
282 0
|
3月前
|
安全 Nacos 数据安全/隐私保护
【技术干货】破解Nacos安全隐患:连接用户名与密码明文传输!掌握HTTPS、JWT与OAuth2.0加密秘籍,打造坚不可摧的微服务注册与配置中心!从原理到实践,全方位解析如何构建安全防护体系,让您从此告别数据泄露风险!
【8月更文挑战第15天】Nacos是一款广受好评的微服务注册与配置中心,但其连接用户名和密码的明文传输成为安全隐患。本文探讨加密策略提升安全性。首先介绍明文传输风险,随后对比三种加密方案:HTTPS简化数据保护;JWT令牌减少凭证传输,适配分布式环境;OAuth2.0增强安全,支持多授权模式。每种方案各有千秋,开发者需根据具体需求选择最佳实践,确保服务安全稳定运行。
263 0
|
4月前
|
Java Nacos 数据库
使用 nacos 搭建注册中心及配置中心
使用 nacos 搭建注册中心及配置中心
98 5
|
4月前
|
NoSQL Java Nacos
SpringCloud集成Seata并使用Nacos做注册中心与配置中心
SpringCloud集成Seata并使用Nacos做注册中心与配置中心
120 3
|
3月前
|
应用服务中间件 Nacos 数据库
Nacos 1.2.1 集群搭建(三) Nginx 配置 集群
Nacos 1.2.1 集群搭建(三) Nginx 配置 集群
61 1