Sentinel Client: 整合Apollo规则持久化

代码拓虹客
• 阅读 1499

在前面的学习过程中,Sentinel 的规则,也就是我们之前定义的限流规则,是通过代码的方式定义好的。这是初始化时需要做的事情,Sentinel 提供了基于API的方式修改规则:

FlowRuleManager.loadRules(List<FlowRule> rules); // 修改流控规则
DegradeRuleManager.loadRules(List<DegradeRule> rules); // 修改降级规则
SystemRuleManager.loadRules(List<SystemRule> rules); // 修改系统规则
AuthorityRuleManager.loadRules(List<AuthorityRule> rules); // 修改授权规则

当我们接入了控制台后,可以通过控制台进行规则的动态修改,问题是当应用程序重启后规则信息就会恢复到初始化的阶段,也就是说后面修改的值会丢失,因为规则信息都是存储在应用的内存中。

为了解决这个问题Sentinel 提供了DataSource 扩展的功能,官方推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现 ReadableDataSource 接口端监听规则中心实时获取变更,流程如下:

Sentinel Client: 整合Apollo规则持久化

扩展的常见方式有推和拉两种模式:

  • 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;
  • 推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 NacosApollo、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。

今天我们主要是讲如何使用 Apollo 来配置规则进行持久化,Apollo是携程开源的配置中心,非常好用

Github地址:https://github.com/ctripcorp/...

在我的书中也有对Apollo使用的详细介绍,等出版了再通知大家。

首先集成需要的依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-apollo</artifactId>
    <version>1.4.1</version>
</dependency>

然后创建 ApolloDataSource 并将其注册至对应的 RuleManager 上即可。比如:

private static void loadRules() {
        // Apollo 中的应用名称,自己定义的
        String appId = "SampleApp";
        // Apollo 的地址
        String apolloMetaServerAddress = "http://localhost:8080";
        System.setProperty("app.id", appId);
        System.setProperty("apollo.meta", apolloMetaServerAddress);
        // 指定环境
        System.setProperty("env", "DEV");
        // Apollo 的命名空间
        String namespaceName = "application";
        // 限流规则的Key, 在Apollo中用此Key
        String flowRuleKey = "flowRules";
        // 限流规则的默认值
        String defaultFlowRules = "[]";
        // 注册数据源
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
            flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
        }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}

到此为止配置就结束了,详细的解释我都写了注释哈。官方文档也是这么写的,问题是如果你刚接触会一头雾水的,为什么?

你不知道在Apollo中怎么配置啊,我们讲的就是说可以用Apollo来作为存储,持久化规则,那么规则怎么配置就需要我们自己去想。

我也是通过看源码才知道怎么去配置的,带着大家一起来看源码吧!

主要就是new ApolloDataSource这里,参数都是通过这里传进去的

public ApolloDataSource(String namespaceName, String flowRulesKey, String defaultFlowRuleValue,
                            Converter<String, T> parser) {
        super(parser);

        Preconditions.checkArgument(!Strings.isNullOrEmpty(namespaceName), "Namespace name could not be null or empty");
        Preconditions.checkArgument(!Strings.isNullOrEmpty(flowRulesKey), "FlowRuleKey could not be null or empty!");

        this.flowRulesKey = flowRulesKey;
        this.defaultFlowRuleValue = defaultFlowRuleValue;

        this.config = ConfigService.getConfig(namespaceName);

        initialize();

        RecordLog.info(String.format("Initialized rule for namespace: %s, flow rules key: %s",
            namespaceName, flowRulesKey));
    }

这边就是对传入的参数赋值,然后看下面这行:

this.config = ConfigService.getConfig(namespaceName);

这就是通过命名空间去Apollo中获取配置,获取完后就执行初始化

private void initialize() {
     initializeConfigChangeListener();
     loadAndUpdateRules();
}

initializeConfigChangeListener是初始化配置的监听器,当配置发生修改时会进入该监听器,也就是说在这个监听器里需要监听配置的修改,然后更新规则

 private void initializeConfigChangeListener() {
        config.addChangeListener(new ConfigChangeListener() {
            @Override
            public void onChange(ConfigChangeEvent changeEvent) {
                ConfigChange change = changeEvent.getChange(flowRulesKey);
                //change is never null because the listener will only notify for this key
                if (change != null) {
                    RecordLog.info("[ApolloDataSource] Received config changes: " + change.toString());
                }
                loadAndUpdateRules();
            }
        }, Sets.newHashSet(flowRulesKey));
 }

loadAndUpdateRules就是更新规则的逻辑了

private void loadAndUpdateRules() {
        try {
            T newValue = loadConfig();
            if (newValue == null) {
                RecordLog.warn("[ApolloDataSource] WARN: rule config is null, you may have to check your data source");
            }
            getProperty().updateValue(newValue);
        } catch (Throwable ex) {
            RecordLog.warn("[ApolloDataSource] Error when loading rule config", ex);
        }
 }

那么配置是怎么来的呢,请看loadConfig

 @Override
 public T loadConfig() throws Exception {
     return loadConfig(readSource());
 }

 public T loadConfig(S conf) throws Exception {
     T value = parser.convert(conf);
     return value;
 }

readSource就是获取我们配置的flowRulesKey的值,那么配置其实就是一个字符串,然后下面通过Json转换

 public String readSource() throws Exception {
     return config.getProperty(flowRulesKey, defaultFlowRuleValue);
 }

我们再返过来看看注册的代码:

 // 注册数据源
 ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
            flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
 }));

重点是ource -> JSON.parseObject(source, new TypeReference<List<FlowRule>>()这行,这不就是转换成List<FlowRule>吗,真相呼之欲出了,也就是在Apollo中配置的就是List<FlowRule>的json格式就行。

我们配置一个试试看:

flowRules = [{"grade":1,"count":11,"resource":"HelloWorld"}]

点击保存并且发布,可以在initializeConfigChangeListener里面设置一个断点,你会发现,当发布配置之后,这边马上就会进来,然后执行其他的逻辑,到此为止整个流程结束。

欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course

PS:目前星球中正在星主的带领下组队学习Sentinel,等你哦!

Sentinel Client: 整合Apollo规则持久化

Sentinel Client: 整合Apollo规则持久化

点赞
收藏
评论区
推荐文章
Spring Boot集成 Sentinel 实现接口流量控制
Hello,大家好,我是麦洛,今天带大家来了解一下SpringBoot如何继承Sentinel来实现接口流量控制Sentinel控制台搭建在我的上一篇文章阿里出品的Sentinel到底是个什么玩意?中,已经介绍过如何准备Sentinel控制台,大家可以直接参考;Sentinel客户端项目搭建首先我们来创建一个测试项目,这里初始化
捉虫大师 捉虫大师
3年前
Sentinel在docker中获取CPU利用率的一个BUG
Sentinel简介微服务治理中限流、熔断、降级是一块非常重要的内容。目前市面上开源的组件也不是很多,简单场景可以使用Guava,复杂场景可以选用Hystrix、Sentinel。今天要说的就是Sentinel,Sentinel是一款阿里开源的产品,只需要做较少的定制开发即可大规模线上使用。从使用感受上来说,它有以下几个优点:轻量级,对性能损耗几乎可以忽略
Easter79 Easter79
3年前
superword开源项目中的定义相似规则
两个词之间的关系有同义、反义、近义(有多近?)、相关(有多相关?)等等。我们如何来判断两个词之间的关系呢?利用计算机能自动找出这种关系吗?当然可以,不仅能找出来,而且还能量化出有多近和有多相关。本文描述了superword(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fgithub
Wesley13 Wesley13
3年前
Activiti工作流引擎学习(一)
1、部署对象和流程定义相关表:RepositoryService act\_re\_deployment:部署对象表:一次部署的多个文件的信息,对于不需要的流程可以删除和修改 act\_re\_procdef:流程定义表:解析bpmn后得到的流程定义规则的信息,工作流系统就是按照流程定义的规则进行的 act\_ge\_bytearray:资
Stella981 Stella981
3年前
Redis Sentinel 源码:Redis的高可用模型分析
摘要:本文通过对RedisSentinel源码的理解,详细说明Sentinel的代码实现方式。RedisSentinel是Redis提供的高可用模型解决方案。Sentinel可以自动监测一个或多个Redis主备实例,并在主实例宕机的情况下自动实行主备倒换。本文通过对RedisSentinel源码的理解,详细说明Sentinel的代码实
Stella981 Stella981
3年前
Redis Sentinel 哨兵模式
RedisSentinel哨兵模式Sentinel介绍Redis的主从模式下,主节点一旦发生故障不能提供服务,需要人工干预,将从节点晋升为主节点,同时还需要修改客户端配置。对于很多应用场景这种方式无法接受。Sentinel(哨兵)架构解决了redis主从人工干预的问题。Redis
Stella981 Stella981
3年前
Sentinel 是如何做限流的
限流是保障服务高可用的方式之一,尤其是在微服务架构中,对接口或资源进行限流可以有效地保障服务的可用性和稳定性。之前的项目中使用的限流措施主要是Guava的RateLimiter。RateLimiter是基于令牌桶流控算法,使用非常简单,但是功能相对比较少。而现在,我们有了一种新的选择,阿里提供的Sentinel。Sentinel是阿里巴巴提供
Stella981 Stella981
3年前
Bypass ngx_lua_waf SQL注入防御(多姿势)
0x00前言ngx\_lua\_waf是一款基于ngx\_lua的web应用防火墙,使用简单,高性能、轻量级。默认防御规则在wafconf目录中,摘录几条核心的SQL注入防御规则:select.(from|limit)(?:(union(.?)select))(?:from\Winformation_schema\W)这边
Stella981 Stella981
3年前
Sentinel断路器与熔断降级
前言Sentinel的熔断降级通过断路器实现,本文通过介绍熔断器的定义、如何构建熔断器、断路器校验逻辑、断路器状态转换、异常/慢调用熔断流量是如何统计等方面梳理断路器的工作原理和实现方式。 一、断路器定义Sentinel中的熔断降级使用断路器实现,先看下断路器概念,来自维基百科的定义:断路器有分简单与较进阶的版本,简单的断路器只需
DDD学习与感悟——总是觉得自己在CRUD怎么办? | 京东云技术团队
我们有时候也会看到一些博客看到或者听到一些同事在说:这个业务有什么难的,不就是CRUD么?在软件生命周期初期,我们通过CRUD这种方式我们可以快速的实现业务规则,交付项目,但随着业务逐渐复杂,通过CRUD这种粗暴方式不可避免地会淹没业务核心规则,产生很多祖传(屎山)代码,系统交接的时候我们经常会听到,上一个开发是SB,或者自嘲自己是在屎山上面继续堆屎。
京东云开发者 京东云开发者
7个月前
开源分析和落地方案—Sentinel篇
作者:京东物流刘达一、Sentinel是什么?Sentinel是从阿里技术体系内诞生并由相关社区从微服务到云原生阶段持续孵化的流量治理组件,在服务熔断限流以及秒级/分钟级监控方面提供了开箱即用的解决方案,此外作为支持云原生的重要探索,还提供了GO语言实现。