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天前
|
缓存 负载均衡 Java
Nacos 集群部署时性能优化配置
Nacos 集群部署时性能优化配置
|
6天前
|
存储 关系型数据库 MySQL
Nacos 的配置过程
Nacos 的配置过程
|
9天前
|
缓存 监控 Java
深入解析Nacos配置中心的动态配置更新技术
深入解析Nacos配置中心的动态配置更新技术
|
10天前
|
关系型数据库 MySQL Nacos
使用 Docker 部署 Nacos 并配置 MySQL 数据源
使用 Docker 部署 Nacos 并配置 MySQL 数据源
25 0
|
12天前
|
Nacos 数据安全/隐私保护
springCloud之nacos服务注册与发现、配置中心
springCloud之nacos服务注册与发现、配置中心
21 0
|
1月前
|
Java Nacos Maven
Sentinel1.8.6更改配置同步到nacos(项目是Gateway)
Sentinel1.8.6 nacos springcloud springcloud-alibaba gateway
|
16天前
|
监控 Java Sentinel
使用Sentinel进行服务调用的熔断和限流管理(SpringCloud2023实战)
Sentinel是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
37 3
|
18天前
|
Java 开发者 Sentinel
Spring Cloud系列——使用Sentinel进行微服务保护
Spring Cloud系列——使用Sentinel进行微服务保护
30 5
|
17天前
|
监控 Java 应用服务中间件
替代 Hystrix,Spring Cloud Alibaba Sentinel 快速入门
替代 Hystrix,Spring Cloud Alibaba Sentinel 快速入门
|
2天前
|
监控 Java 应用服务中间件
SpringCloud面试之流量控制组件Sentinel详解
SpringCloud面试之流量控制组件Sentinel详解
9 0