基于Nacos实现Sentinel规则持久化

一、Sentinel使用痛点

SpringCloudAlibaba帮我们提供了微服务的限流、熔断、降级组件Sentinel。并且它的功能非常强大,使用起来也非常方便,只需要给需要限流的资源添加注解,配置对应的规则,就能实现效果。(使用可以参考Sentinel使用)但是有个问题就是Sentinel的规则是保存在客户端的内存中,控制台(服务端)查询规则也是基于客户端内存查询。

这样就存在一个很严重的问题,如果客户端发生了重启那么配置的众多规则都会失效。想想都觉得很严重,谁还敢在生产环境使用它。那么基于这个问题,我们有多种方案可以来解决。

二、解决方案

2.1 保存本地文件

既然是担心规则保存在客户端内存中会丢失,那么我们可以将规则持久化到本地文件,但是这样也有一个问题,如果微服务是高可用部署,有多个实例节点,那么保存到本地文件就不可取了。

2.2 保存数据库

将规则持久化到数据库中,这样多个节点访问同一个数据库也能拿到配置,这样的缺点是如果规则变化从数据库中直接修改,微服务则没那么容易感知到变化,不过也不是解决不了,可以使用canel组件,监听mysql的binlog日志,从而刷新规则,但这这样又要引入新的中间件,增加了系统的复杂性。

2.3 保存到Nacos

我们知道nacos的客户端在启动时会主动从服务端拉取一次配置,之后会通过延迟定时任务拉取配置,同时对配置文件配置监听器。双层保证服务端的变化能被客户端感知到,基于Nocos本来的特性,再整合Sentinel的扩展点,我们就可以实现如下图的结构。
在Nacos服务端或者Sentinel控制台修改配置,都能将规则推送到Sentinel客户端。并且在Nacos服务端修改配置规则Sentinel控制台的规则会发生变化,在Sentinel控制台修改规则,Naocs的配置文件就会发生变化。
在这里插入图片描述

三、规则持久化到Nacos

梳理一下配置变更的两条线

  1. Nacos服务端修改配置,规则同步到Sentinel客户端及Sentinel控制台
  2. Sentinel控制台修改配置,规则同步到Sentinel客户端和Nacos服务端

3.1 Nacos服务端修改配置

  1. 我们在使用nacos作为规则持久化时需要引入一下相关依赖。
 <!--sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <!--sentinel持久化 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
    
        <!-- nacos服务注册与发现 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
  1. spring-cloud-starter-alibaba-sentinel这个依赖会包含spring-cloud-starter-alibaba-sentinel-datasource
    在这里插入图片描述
  2. spring-cloud-starter-alibaba-sentinel-datasource依赖中引入了关键类NacosDataSourceFactoryBean
    在这里插入图片描述
  3. NacosDataSourceFactoryBean的构造方法中实例化了NacosDataSource
public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource> {
public NacosDataSource getObject() throws Exception {
		// 中间代码省略...
      return new NacosDataSource(properties, this.groupId, this.dataId, this.converter);
    }
}
  1. NacosDataSource由sentinel-datasource-nacos依赖引入
    在这里插入图片描述
  2. NacosDataSource的构造方法中会定义监听器,并且将监听器和配置文件绑定,这样当Nacos服务端修改配置后,客户端就能拿到最新的规则,并且将规则更新内存中。同时会先从Nacos服务拉去一次配置做初始化。
public NacosDataSource(final Properties properties, final String groupId, final String dataId, Converter<String, T> parser) {
        super(parser);
        this.pool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(1), new NamedThreadFactory("sentinel-nacos-ds-update", true), new DiscardOldestPolicy());
        this.configService = null;
        if (!StringUtil.isBlank(groupId) && !StringUtil.isBlank(dataId)) {
            AssertUtil.notNull(properties, "Nacos properties must not be null, you could put some keys from PropertyKeyConst");
            this.groupId = groupId;
            this.dataId = dataId;
            this.properties = properties;
            // 1.定义监听器,当配置发生变更监听器就能获取最新的配置
            this.configListener = new Listener() {
                public Executor getExecutor() {
                    return NacosDataSource.this.pool;
                }

                public void receiveConfigInfo(String configInfo) {
                    RecordLog.info("[NacosDataSource] New property value received for (properties: {}) (dataId: {}, groupId: {}): {}", new Object[]{properties, dataId, groupId, configInfo});
                    T newValue = NacosDataSource.this.parser.convert(configInfo);
                    NacosDataSource.this.getProperty().updateValue(newValue);
                }
            };
            // 2.将监听器和配置文件绑定
            this.initNacosListener();
            // 3.从Nacos服务端拉取配置放在内存中
            this.loadInitialConfig();
        } else {
            throw new IllegalArgumentException(String.format("Bad argument: groupId=[%s], dataId=[%s]", groupId, dataId));
        }
    }

3.2 Sentinel控制台修改配置

  1. Sentinel控制台发布规则后会调用Sentinel客户端的ModifyRulesCommandHandler,将修改的规则传过来。

  2. ModifyRulesCommandHandler的handle方法中是真正的处理逻辑,这里以流控规则为例,其他规则一样只是代码没展示。在Handle方法中会先将最新的规则加载到内存中,并且进行规则的持久化处理。

@CommandMapping(name = "setRules", desc = "modify the rules, accept param: type={ruleType}&data={ruleJson}")
public class ModifyRulesCommandHandler implements CommandHandler<String> {
@Override
    public CommandResponse<String> handle(CommandRequest request) {
    	// 省略部分代码...
        if (FLOW_RULE_TYPE.equalsIgnoreCase(type)) {
            List<FlowRule> flowRules = JSONArray.parseArray(data, FlowRule.class);
            // 1.将规则加载到内存中
            FlowRuleManager.loadRules(flowRules);
            // 2.规则持久化(如果增加了扩展,默认没有实现)
            if (!writeToDataSource(getFlowDataSource(), flowRules)) {
                result = WRITE_DS_FAILURE_MSG;
            }
            return CommandResponse.ofSuccess(result);
        }
}
  1. 上面的持久化最终会调用到我们自己实现的Nacos实现类中,最终将配置发布到Nacos服务端。
public class NacosWritableDataSource<T> implements WritableDataSource<T> {
@Override
    public void write(T t) throws Exception {
        lock.lock();
        try {
            configService.publishConfig(dataId, groupId, this.configEncoder.convert(t), ConfigType.JSON.getType());
        } finally {
            lock.unlock();
        }
    }
}

3.3 Nacos数据源整合到Sentinel中

  1. application.yml中需要对Nacos数据进行配置(以流控规则为例)
spring:
  application:
    name: sentinel-rule-push-demo  #微服务名称
  #配置nacos注册中心地址
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        # 添加sentinel的控制台地址
        dashboard: 127.0.0.1:8080
      datasource:
        flow-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-flow
            groupId: SENTINEL_GROUP   # 注意groupId对应Sentinel Dashboard中的定义
            data-type: json
            rule-type: flow
  1. 将Nacos数据源注册为Sentinel的写数据源
public class NacosDataSourceListener implements ApplicationListener<ContextRefreshedEvent> {
    @Autowired
    private SentinelProperties sentinelProperties;
	@Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
    	// 1.获取流控规则数据源信息
        NacosDataSourceProperties nacosDataSourceProperties = sentinelProperties.getDatasource().get("flow-rules").getNacos();
        // 2.初始化流控规则数据源
        WritableDataSource<List<FlowRule>> writableDataSource = new NacosWritableDataSource<>(
                nacosDataSourceProperties.getServerAddr(), nacosDataSourceProperties.getGroupId(), nacosDataSourceProperties.getDataId(), JSON::toJSONString);
        // 将Nacos数据源注册为Sentinel写数据源
        WritableDataSourceRegistry.registerFlowDataSource(writableDataSource);
    }
}
  • 28
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: b'sentinel规则持久化nacos'的意思是将Sentinel规则持久化Nacos中,使得在规则发生变化时,可以自动同步至Nacos中,保证系统的稳定性和可靠性。这样做也便于管理和维护规则信息。 ### 回答2: Sentinel规则持久化是指将在Sentinel中配置的规则信息保存到外部存储器中,以便于在应用启动时,可以从外部存储器中加载规则,从而实现规则的自动化配置。 Nacos是一款开源的动态服务发现、配置管理和服务管理平台。它可以用于管理应用程序的配置信息、服务发现和服务注册。Sentinel是阿里巴巴开源的一款微服务框架。它可以用于在分布式系统中实现流量控制、熔断降级和系统负载保护等功能。 在分布式环境中,由于存在多个节点,这些节点之间需要共享配置信息和规则信息。传统的配置和规则信息的管理方式比较繁琐,需要手动配置,而且容易出现人为错误。因此,将规则信息持久化Nacos中,可以实现自动化配置和管理,从而提高规则信息的管理效率和运维效率。 具体来说,Sentinel可以通过配置文件的方式将规则信息持久化Nacos中。首先需要在Nacos中创建一个配置集群,然后在Sentinel中进行配置,指定配置的数据源为Nacos。这样就可以将Sentinel中的规则信息保存到Nacos中。 在系统运行时,Sentinel可以从Nacos中加载规则信息,并根据规则信息对流量进行控制。如果规则信息发生变化,Sentinel也可以及时地更新规则信息。因此,利用Nacos持久化规则信息,可以实现规则的动态管理和自动化配置,提高系统的稳定性和可靠性。 总之,Sentinel规则持久化Nacos中,可以实现规则的自动化管理和动态配置。它具有管理效率高、运维效率高、稳定性好等优点。因此,在分布式环境中,将规则信息持久化Nacos中,是一种非常值得推广的做法。 ### 回答3: Sentinel规则持久化Nacos是为了让Sentinel控制台中配置的规则在重启后仍能够保留,避免重启后规则丢失需要重新手动配置的问题。Nacos是一个开源的注册中心和配置中心,支持分布式场景下的服务注册、配置管理和服务发现。在Sentinel中,我们可以通过将规则持久化Nacos中来实现持久化的功能。 首先,我们需要在控制台中配置Nacos的相关信息,包括Nacos Server地址、Data ID和Group信息等。其中,Data ID和Group信息用于标识Sentinel规则的唯一性。 接下来,我们需要通过编写代码来实现Sentinel规则持久化Nacos中。具体实现方式可以参考官方文档中提供的示例代码,主要包括以下几个步骤: 1. 创建Nacos的配置管理客户端,可以通过NacosFactory.createConfigService()方法获取。 2. 将Sentinel规则序列化成JSON字符串,可以通过Jackson等工具实现。 3. 调用Nacos的API,将JSON字符串保存到Nacos中,例如使用configService.publishConfig()方法。 4. 在Sentinel应用启动时,需要从Nacos中读取保存的规则信息,并将其解析成Sentinel规则对象,例如使用configService.getConfig()方法获取Nacos中的配置信息,之后再调用SentinelRuleParser.parseRules()方法将其转换为Sentinel规则对象。 5. 在控制台中修改或删除规则时,需要通过调用Nacos的API来更新或删除相应的配置信息,例如使用configService.publishConfig()和cconfigService.removeConfig()方法实现。 通过以上步骤,我们就可以实现Sentinel规则持久化Nacos中的功能,保证了应用重启后规则仍能够得到保留。同时,使用Nacos作为规则持久化的中心,还能够实现多节点之间的规则同步和分布式配置的管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值