阿里面试这样问:Nacos用了 push 还是 pull模式 ?

  • 对于 Nacos
    大家应该都不太陌生,出身阿里名声在外,能做动态服务发现、配置管理,非常好用的一个工具。然而这样的技术用的人越多面试被问的概率也就越大,如果只停留在使用层面,那面试可能要吃大亏。

    比如我们今天要讨论的话题, Nacos 在做配置中心的时候,配置数据的交互模式是服务端推过来还是客户端主动拉的?
    在这里插入图片描述
    这里我先抛出答案:客户端主动拉的!

接下来咱们扒一扒 Nacos 的源码,来看看它具体是如何实现的?

配置中心

聊 Nacos 之前简单回顾下配置中心的由来。

简单理解配置中心的作用就是对配置统一管理,修改配置后应用可以动态感知,而无需重启。

因为在传统项目中,大多都采用静态配置的方式,也就是把配置信息都写在应用内的 yml 或 properties 这类文件中,如果要想修改某个配置,通常要重启应用才可以生效。

但有些场景下,比如我们想要在应用运行时,通过修改某个配置项,实时的控制某一个功能的开闭,频繁的重启应用肯定是不能接受的。

尤其是在微服务架构下,我们的应用服务拆分的粒度很细,少则几十多则上百个服务,每个服务都会有一些自己特有或通用的配置。假如此时要改变通用配置,难道要我挨个改几百个服务配置?很显然这不可能。所以为了解决此类问题配置中心应运而生。
在这里插入图片描述
推与拉模型
客户端与配置中心的数据交互方式其实无非就两种,要么推 push ,要么拉 pull 。

推模型
客户端与服务端建立 TCP 长连接,当服务端配置数据有变动,立刻通过建立的长连接将数据推送给客户端。

优势:长链接的优点是实时性,一旦数据变动,立即推送变更数据给客户端,而且对于客户端而言,这种方式更为简单,只建立连接接收数据,并不需要关心是否有数据变更这类逻辑的处理。

弊端:长连接可能会因为网络问题,导致不可用,也就是俗称的 假死 。连接状态正常,但实际上已无法通信,所以要有的心跳机制 KeepAlive 来保证连接的可用性,才可以保证配置数据的成功推送。

拉模型
客户端主动的向服务端发请求拉配置数据,常见的方式就是轮询,比如每3s向服务端请求一次配置数据。

轮询的优点是实现比较简单。但弊端也显而易见,轮询无法保证数据的实时性,什么时候请求?间隔多长时间请求一次?都是不得不考虑的问题,而且轮询方式对服务端还会产生不小的压力。

长轮询
开篇我们就给出了答案, nacos 采用的是客户端主动拉 pull 模型,应用长轮询( Long Polling )的方式来获取配置数据。

额?以前只听过轮询,长轮询又是什么鬼?它和传统意义上的轮询(暂且叫短轮询吧,方便比较)有什么不同呢?

短轮询
不管服务端配置数据是否有变化,不停的发起请求获取配置,比如支付场景中前段JS轮询订单支付状态。

这样的坏处显而易见,由于配置数据并不会频繁变更,若是一直发请求,势必会对服务端造成很大压力。还会造成推送数据的延迟,比如:每10s请求一次配置,如果在第11s时配置更新了,那么推送将会延迟9s,等待下一次请求。
在这里插入图片描述
为了解决短轮询的问题,有了长轮询方案。

长轮询
长轮询可不是什么新技术,它不过是由服务端控制响应客户端请求的返回时间,来减少客户端无效请求的一种优化手段,其实对于客户端来说与短轮询的使用并没有本质上的区别。

客户端发起请求后,服务端不会立即返回请求结果,而是将请求挂起等待一段时间,如果此段时间内服务端数据变更,立即响应客户端请求,若是一直无变化则等到指定的超时时间后响应请求,客户端重新发起长链接。

在这里插入图片描述

Nacos初识

为了后续演示操作方便我在本地搭了个 Nacos 。 注意: 运行时遇到个小坑,由于 Nacos 默认是以 cluster 集群的方式启动,而本地搭建通常是单机模式 standalone ,这里需手动改一下启动脚本 startup.X 中的启动模式。
在这里插入图片描述
直接执行 /bin/startup.X 就可以了,默认用户密码均是 nacos 。
在这里插入图片描述
几个概念
Nacos 配置中心的几个核心概念: dataId 、 group 、 namespace ,它们的层级关系如下图
在这里插入图片描述
dataId :是配置中心里最基础的单元,它是一种 key-value 结构, key 通常是我们的配置文件名称,比如: application.yml 、 mybatis.xml ,而 value 是整个文件下的内容。

目前支持 JSON 、 XML 、 YAML 等多种配置格式。
在这里插入图片描述
group :dataId配置的分组管理,比如同在dev环境下开发,但同环境不同分支需要不同的配置数据,这时就可以用分组隔离,默认分组 DEFAULT_GROUP 。

namespace :项目开发过程中肯定会有 dev 、 test 、 pro 等多个不同环境, namespace 则是对不同环境进行隔离,默认所有配置都在 public 里。

架构设计
下图简要描述了 nacos 配置中心的架构流程。

客户端、控制台通过发送Http请求将配置数据注册到服务端,服务端持久化数据到Mysql。

客户端拉取配置数据,并批量设置对 dataId 的监听发起长轮询请求,如服务端配置项变更立即响应请求,如无数据变更则将请求挂起一段时间,直到达到超时时间。为减少对服务端压力以及保证配置中心可用性,拉取到配置数据客户端会保存一份快照在本地文件中,优先读取。
在这里插入图片描述
这里我省略了比较多的细节,如鉴权、负载均衡、高可用方面的设计(其实这部分才是真正值得学的,后边另出文讲吧),主要弄清客户端与服务端的数据交互模式。

下边我们以Nacos 2.0.1版本源码分析,2.0以后的版本改动较多,和网上的很多资料略有些不同 地址:https://github.com/alibaba/nacos/releases/tag/2.0.1

客户端源码分析
Nacos 配置中心的客户端源码在 nacos-client 项目,其中 NacosConfigService 实现类是所有操作的核心入口。

说之前先了解个客户端数据结构 cacheMap ,这里大家重点记住它,因为它几乎贯穿了Nacos客户端的所有操作,由于存在多线程场景为保证数据一致性, cacheMap 采用了 AtomicReference 原子变量实现。

/**
 * groupKey -> cacheData.
 */
private final AtomicReference<Map<String, CacheData>> cacheMap = new 
AtomicReference<Map<String, CacheData>>(new HashMap<>
  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值