基于ZooKeeper实现配置中心系统

1,200 阅读3分钟

1 背景

1.1 分布式技术的成熟,分布式的广泛流行

分布式集群下的配置管理实现方式,在当下这个时代已然是分布式的时代,结合上国家倡导的新基建的大背景,云服务和虚拟化也已经从高大上的名词变成了接地气的技术。 现在各个公司的服务,能用零碎分布式的多台小型机器部署,就尽量不用大型计算机处理,一个非常经典的原因就是单点故障

1.2 分布式集群上的配置文件需要统一管理

现在,我们以JavaWeb为例,你有一个分布式部署的JavaWeb服务,这些服务执行最简单的CRUD工作,下面连接的是MySQL,现在你需要在分布式部署的每台服务器上都写入同样的配置文件

jdbc.user=root
jdbc.password=123456
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://xxx.xxx.xxx.xxx:3306/database?useUnicode=true&characterEncoding=utf8

这时你面对几个问题:

  1. 哪里可以统一看到自己的集群配置
  2. 如果我需要修改连接的DB(比如主从切换),难道要一台台ssh上去改吗?

简单的解决办法就是写一个脚本,批量上传配置文件到每台服务器上的相应位置,然后重启服务。但是这样的问题在于没有办法统一管理和查看配置,而且存在上传失败的问题

可以发现配置的属性比较类似于dubbo的注册中心,保证配置文件在分布式服务下的一致性

1.3 配置管理文件的几种实现方案

Zookeeper
Eureka
git
redis

关于这几种配置存储方式的比较,我们会单独开一个坑去探讨。本次我们先讨论ZooKeeper的特性如何保证并实现高可用的配置管理系统。

1.4 采用ZooKeeper可能存在问题

由于ZooKeeper在CAP原理(C-数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个)上只能满足CP(数据一致和分区故障容错),zk在master节点故障的时候整个zk服务选主过程不可用,因此会有稳定性问题。

解决的方案是在zk集群和使用者之间构造一层缓存层

2 总体结构

总体结构

2.1 搭建一个zk集群

zookeeper.apache.org/
首先需要搭建一个zk的集群,可以参照官网上的教程执行,本文不再赘述

2.2 开发client端

针对不同的开发语言(Java,C++,python,go),不同的环境(Spring...),开发配置中心client端,cient端需要做到的事情:

  1. 封装zkClient操作,支持对于配置的文件缓存+内存缓存功能
  2. 通过zkClient的watcher订阅机制订阅监听zk节点变更事件,以便于及时刷新缓存
  3. 对于例如Spring的环境,需要支持#{property}或者对于SpringBoot支持@Value 等注解的配置注入功能

2.3 开发管理端

管理端的功能是封装对于zk文件的查看和修改逻辑,以便于对配置文件进行统一管理,这里可以支持的操作有:

  • 权限控制,通过CAS系统建立账号体系,管理端维护<账户名-账户角色>的映射关系,对于不同角色的账户暴露不同的操作权限
  • 查看目录结构和查看文件,即zk的ls和get命令
  • 删除配置文件,即zk的delete命令
  • 发布配置(发送watcher事件到client端),即对zk指定位置的文件进行修改操作
  • 配置支持回滚操作,即zk的路径中支持版本号,发布操作时copy出一份原配置副本后再执行配置修改

reference

[1] 《从Paxos到ZooKeeper分布式一致性原理与实践》
[2] 服务注册中心,Eureka与Zookeeper比较
[3] ZooKeeper官方文档[OL]. zookeeper.apache.org/doc/