背景
在分布式系统中,一次构建、发布、上线是非常非常重的一个过程,它不像单机时代那样重启一台机器、一个进程就可以了,在分布式系统中,它涉及到将软件包分发到可能超过几千台机器,然后将几千台机器上的应用进程一一重启,这么一个过程,一个应用一次完整的发布过程需要多长时间,相信很多核心系统的同学都深有体会;
而在不停应用集群的前提下,调整应用集群的运行特征,是作为一个分布式系统必须解决的一个问题。
从这个角度来看:统一配置中心是一个分布式系统都必须具有的一个角色。
配置中心架构
image.png配置中心关注点
- 配置中心的弱依赖
应用应该弱依赖于配置中心,如果配置中心挂掉,不能影响应用的正常运行
所以客户端应该缓存配置数据 - 配置存储应该做好容灾备份
配置中心的数据是不能丢失的,如果丢失了,估计几百个配置项就无法寻回,这种是无法允许的 - 推送时延和推送成功率
如上节使用zookeeper来说,watcher机制并不能保证每一次配置的更改都推送给客户端,这种对于应用也是一件无法允许的事情 - 灰度
如果使用zookeeper来做配置中心,做灰度是一件很难的事情,不是说不能做,是需要客户端去配合过滤一些不必要的数据,而这种造成了网络的垃圾开销及客户端的复杂度,下文会详细说 - 集中入口及变更审计能力
Zookeeper配置管理的局限性
- 配置数据大小的问题
对于Zookeeper来说,数据大小直接影响了它的读写性能,身单个节点数据越大,对网络方面的吞吐就会造成影响,而zookeeper也添加了单个节点数据内容不能超过1M的限制,这个问题带来的解决方案有:
1)一个应用一个节点,节点的内容存放所有配置数据,结果是一个节点数据估计有几十K,当Zookeeper进行数据同步时,带宽估计会被它全部吃掉;例子有:
http://blog.jobbole.com/112233/
2)一个Key一个节点,节点内容对应于Value,一个应用估计对应于几十个节点,运维管理成本大幅上升 - 配置数据环境属性不同的问题
在现实中,配置数据是要具有环境属性的,相当一部分配置在不同的环境必须设定不同的值,但是也有相当的另一部分配置在不同的环境要设定为完全一致的值。所以从某个应用的视角看,其100个配置项,可能有50个是每个环境要不同的值的,而另50个是不区分环境;而zookeeper只要把数据写入了znode中,必然会把数据通知给各个客户端,这种做法带来了两个问题:
1)垃圾网络开销;
2)应用需要按照规则进行过滤不需要的配置信息; - 集群下(Observer模式)同步的问题
zookeeper为了提升写性能,增加了一直Observer的部署节点,该类型节点下不参与投票选举,只接收投票结果,该种模式一般多用于跨数据中心的部署,然而涉及到跨数据中心,就意味着网络抖动的问题,每一次网络抖动都会导致数据同步的重新进行(无论是差异化同步或者全部同步),这种情况下会导致连接到observer节点的数据不是最新的,从而导致配置数据无法及时通知到达 - Watcher注册机制
许多人选择使用zookeeper做配置中心关键的一点就是watcher机制,但是使用watcher有几个要注意点:- Watches通知是一次性的,必须重复注册.
- 发生CONNECTIONLOSS之后,只要在session_timeout之内再次连接上(即不发生SESSIONEXPIRED),那么这个连接注册的watches依然在。
- 节点数据的版本变化会触发NodeDataChanged,注意,这里特意说明了是版本变化。存在这样的情况,只要成功执行了setData()方法,无论内容是否和之前一致,都会触发NodeDataChanged。
- 对某个节点注册了watch,但是节点被删除了,那么注册在这个节点上的watches都会被移除。
- 同一个zk客户端对某一个节点注册相同的watch,只会收到一次通知。即
Watcher对象只会保存在客户端,不会传递到服务端。
另外最主要一点就是zookeeper并不保证每次节点的变化都会通知到客户端,原因是因为当一次数据修改,通知客户端,客户端再次注册watch,在这个过程中,可能数据已经发生了许多次数据修改
网友评论