原文始发于:利用Zookeeper实现 - 数据发布订阅
数据发布/订阅
所谓的数据发布/订阅,意思是发布者将数据发布到Zookeeper上的一个或一系列节点上,通过watcher机制,客户端可以监听(订阅)这些数据节点,当这些节点发生变化时,Zookeeper及时地通知客户端,从而达到动态获取数据的目的。
一种常见的场景就是配置中心。随着应用越来越多,功能越来越复杂,机器也越来越多,对于一些公共的程序配置,譬如各种功能的开关、数据库的配置、服务器的地址等,如果每个应用每个机器仍然单独维护,当要修改配置时就得一个一个地修改,这样显然非常不方便。
这些公共的配置信息通常具备以下3个特性:
- 数据量通常比较小
- 数据内容在运行时发生动态变化
- 集群中各机器共享、配置一致
可以将这些配置抽取出来,交给配置中心统一管理起来。配置中心的架构一般是这样:
开源配置中心
开源的配置中心有很多,各有特点,这里只列出几个进行简单地介绍。
Ctrip Apollo
github地址:https://github.com/ctripcorp/apollo
介绍:Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
Disconf
github地址:https://github.com/knightliao/disconf
介绍:专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」。主要目标是部署极其简单、部署动态化、统一管理、一个jar包,到处运行。
Spring Cloud Config
github地址:https://github.com/spring-cloud/spring-cloud-config
介绍:Spring Cloud Config是一个基于http协议的远程配置实现方式,通过统一的配置管理服务器进行配置管理,客户端通过https协议主动的拉取服务的的配置信息,完成配置获取。
Nacos
github地址:https://github.com/alibaba/nacos
介绍:Nacos是阿里最近才开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
利用Zookeeper实现一个配置中心
开源的配置中心当然都很优秀,但是现在我们还是先利用Zookeeper来实现一个属于自己的配置中心。
我们的配置中心保存的配置信息十分简单,就是JDBC连接MySQL需要用的连接信息。这些连接信息将转化为JSON字符串,保存在Zookeeper上的一个节点中;应用程序(通过线程模拟的)从Zookeeper中读取这些配置信息,然后查询数据库;当修改数据库连接信息时(切换数据库),应用程序能及时的拉取新的连接信息,使用新的连接查询数据库。
定义一个 MysqlConfig 类,方便使用 FastJSON 将配置信息在JSON字符串与对象之间做转换。
@AllArgsConstructor
@Data
public class MysqlConfig {
private String url;
private String driver;
private String username;
private String password;
}
最开始,将Zookeeper上节点的配置信息初始化为 test 数据库的连接信息,然后启动 N 个线程(模拟应用程序),读取连接信息并查询数据,同时设置监听节点;等待 10 秒钟之后,将配置切换为 test2 数据库的连接信息,这时应用程序将受到配置变更的通知,然后获取信息连接信息,重新查询数据库。
// 工具类
public class ZKUtils {
private static final String zkServerIps = "master:2181,hadoop2:2181";
public static synchronized CuratorFramework getClient() {
CuratorFramework client = CuratorFrameworkFactory.builder().connectString(zkServerIps)
.sessionTimeoutMs(6000).connectionTimeoutMs(3000) //.namespace("LeaderLatchTest")
.retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
return client;
}
}
// 配置中心示例,模拟数据库切换
public class ConfigCenterTest {
// test 数据库的 test1 表
private static final MysqlConfig mysqlConfig_1 = new MysqlConfig("jdbc:mysql://master:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false", "com.mysql.jdbc.Drive