Spring Cloud Alibaba --Nacos配置中心实现原理

如果让我们自己实现一个分布式配置中心,从那些方面考虑呢?

服务器端的配置保存(持久化)?
服务器端提供什么样的访问api?
数据变化之后如何通知到客户端?push(服务端主动推送到客户端)、pull(客户端主动拉去数据)? -> 长轮训( pull数据量很大会怎么办)
客户端如何去获得远程服务的数据?
安全性
刷盘(本地缓存)

那么我们看看 Nacos 是否按照我们的设想实现的呢?
  • Nacos客户端从服务端获取数据的example在这里插入图片描述
  • 上述的代码首先创建一个congfigService ,是通过反射的方式创建一个 NacosConfigService
    在这里插入图片描述
  • 通过getConfig 获取服务器上配置的内容
    在这里插入图片描述
  • 通过http 的方式向服务端获取远端服务的配置内容
    在这里插入图片描述
  • 服务端通过 SpringMVC的方式提供一个Get 方法供客户端获取数据使用
    在这里插入图片描述
    至此整个初次获取服务端配置信息的流程就完成了,那么大家考虑一个问题,如果服务端的数据发生变化时,客户端是是如何感知的?是通过定时的pull 还是服务端自动推送呢(push)?
一、客户端如何将可能发生变化的数据告诉给服务端?

刚刚看上面的代码,客户端通过反射的方式创建了一个NacosConfigService ,那么我们是否可以通过 NacosConfigService 创建来入手呢?
在这里插入图片描述
那么我们看看是否应对上述的话
在这里插入图片描述

  • 接下来核心内容就要到了
 public NacosConfigService(Properties properties) throws NacosException {
        ValidatorUtils.checkInitParam(properties);
        String encodeTmp = properties.getProperty(PropertyKeyConst.ENCODE);
        if (StringUtils.isBlank(encodeTmp)) {
            encode = Constants.ENCODE;
        } else {
            encode = encodeTmp.trim();
        }
        initNamespace(properties);
        agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
        agent.start();
        worker = new ClientWorker(agent, configFilterChainManager, properties); //核心方法,我没看看是否会这里面实现 上述的 pull 或者push 呢?
    }
  • 该类的定义如下: 初始化2个线程池的定义, 跟一个定时执行的线程池
 public ClientWorker(final HttpAgent agent, final ConfigFilterChainManager configFilterChainManager, final Properties properties) {
        this.agent = agent;
        this.configFilterChainManager = configFilterChainManager;
        // Initialize the timeout parameter
        init(properties);
        executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("com.alibaba.nacos.client.Worker." + agent.getName());
                t.setDaemon(true);
                return t;
            }
        });

        executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName());
                t.setDaemon(true);
                return t;
            }
        });

        executor.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                try {
                    checkConfigInfo(); //定时的检查配置是否发生变化
                } catch (Throwable e) {
                    LOGGER.error("[" + agent.getName() + "] [sub-check] rotate check error", e);
                }
            }
        }, 1L, 10L, TimeUnit.MILLISECONDS);
    }

  • 分批去检查配置内容是否发生变化
    在这里插入图片描述

  • 长轮询任务执行内容:
    在这里插入图片描述

  • 检查本地缓存的内容是否发生变化
    在这里插入图片描述
    在这里插入图片描述
    -通过事件监听通知本地缓存(本地cache 跟本地文件 不一致,用本地文件的内容作为最新内容,通知给客户端)通过checkListenerMd5()方法我们可以看出发送一个通知,代码如下:
    在这里插入图片描述

  • 本地文件拿不到最新内容,就要从远端服务器获取最新内容。
    在这里插入图片描述
    -请求服务端获取发生变化的组装过程在这里插入图片描述

  • 真正的请求在这里插入图片描述

二、 服务端拿到请求后如何处理?

1. 长轮询检查 客户端认为会发生变化的groupKey
在这里插入图片描述
2.判断兼容性质
在这里插入图片描述
3.如果检查到可能变化的groupKey 在服务器端确实发生变化,则将变化的groupKey 反回给客户端。
在这里插入图片描述
4.如果没有检查出变化,则30s-0.5s 后再检查一次,看是否发生变化,这次检查完不管有没有发生变化,都进行返回。
在这里插入图片描述
5.通过开启一个定时任务的线程去进行再次检查,并将检查后的结果进行返回。
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值