<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-zookeeper</artifactId>
<version>5.2.1</version>
</dependency>
ZooKeeper 集群管理器 (vertx-zookeeper)
该组件为 Vert.x 提供了基于 Apache ZooKeeper 的集群管理器(Cluster Manager)实现。
该实现完整对接了 Vert.x 的集群 SPI 规范,因此你可以使用它直接替代 vertx-hazelcast 作为集群底座。
在项目构建描述文件中添加以下依赖:
-
Maven(在
pom.xml中):
-
Gradle(在
build.gradle文件中):
compile 'io.vertx:vertx-zookeeper:5.2.1'
在 Vert.x 中,集群管理器承担以下核心协作职责:
-
集群中 Vert.x 节点的自动发现与成员拓扑维护
-
维护全集群范围的 Event Bus 主题订阅者映射表(以便获知哪些节点对哪些 Event Bus 地址感兴趣)
-
分布式映射(Distributed Map)支持
-
分布式锁(Distributed Locks)
-
分布式计数器(Distributed Counters)
请注意:集群管理器并不负责节点间的 Event Bus 实际消息传输;节点间的数据通信由 Vert.x 直接通过底层的 TCP 连接通道高效完成。
运行机制原理
本模块底层基于成熟的 Apache Curator 框架封装,而非直接裸调 ZooKeeper 原始客户端。因此项目隐式依赖了 Curator 所需的类库,如 guava、slf4j 以及 zookeeper 客户端。
由于 ZooKeeper 采用树状分层目录结构存储元数据,我们以根路径作为隔离命名空间(Namespace)。默认根路径在 default-zookeeper.json 中配置为 io.vertx。
此外,还有 5 个子路径用于支撑 Vert.x 集群管理器的各项运行时功能(除根命名空间外,其余子路径通常由框架内部管理):
-
/io.vertx/cluster/nodes/:记录所有活跃的 Vert.x 集群节点信息 -
/io.vertx/asyncMap/$name/:记录通过io.vertx.core.shareddata.AsyncMap接口创建的异步分布式映射数据 -
/io.vertx/asyncMultiMap/$name/:记录通过io.vertx.core.spi.cluster.AsyncMultiMap接口创建的异步多值映射数据 -
/io.vertx/locks/:维护分布式锁状态 -
/io.vertx/counters/:维护全局分布式计数器
使用 ZooKeeper 集群管理器
如果你使用 Vert.x 命令行工具启动应用,需确保将对应的 jar 包(如 vertx-zookeeper-5.2.1.jar)放置在 Vert.x 安装目录下的 lib 目录中。
在基于 Maven 或 Gradle 的工程中,只需直接引入依赖 io.vertx:vertx-zookeeper:5.2.1 即可。
当该 jar 包存在于应用的类路径(Classpath)中时,Vert.x 在启动集群模式时将自动检测并将其激活为默认集群管理器。 请确保类路径中没有其他集群管理器实现,否则 Vert.x 可能会错误加载其他的集群实现。
若通过代码方式嵌入式启动 Vert.x,可以通过配置选项显式传入该集群管理器:
ClusterManager mgr = new ZookeeperClusterManager();
Vertx.builder()
.withClusterManager(mgr)
.buildClustered().onComplete(res -> {
if (res.succeeded()) {
Vertx vertx = res.result();
// 集群 Vert.x 实例就绪
} else {
// 启动失败!
}
});
配置 ZooKeeper 集群管理器
集群管理器默认加载打包在 jar 内部的 default-zookeeper.json 配置文件。
若需覆盖默认配置,可以在类路径根目录下提供自定义的 zookeeper.json 文件。
如果将应用打包为可执行 Fat Jar,zookeeper.json 必须位于 Fat Jar 的根路径下;若使用外部配置文件,必须将包含该文件的 目录 追加到类路径中。例如,配合 Vert.x 启动器(Launcher)使用时配置如下:
# 如果 zookeeper.json 位于当前目录:
java -jar ... -cp . -cluster
vertx run MyVerticle -cp . -cluster
# 如果 zookeeper.json 位于 conf 目录下:
java -jar ... -cp conf -cluster
另一种更灵活的覆盖方式是通过系统属性 vertx.zookeeper.config 直接指定外部文件路径:
# 加载文件系统中的外部绝对/相对路径配置:
java -Dvertx.zookeeper.config=./config/my-zookeeper-conf.json -jar ... -cluster
# 或者加载类路径中指定包下的配置文件:
java -Dvertx.zookeeper.config=classpath:my/package/config/my-cluster-config.json -jar ... -cluster
当系统属性 vertx.zookeeper.config 存在时,其优先级高于类路径下的任何 zookeeper.json;若根据该系统属性加载失败,系统将平滑降级至 zookeeper.json 或默认配置。
详细的配置项说明请参阅 default-zookeeper.json 中的内置注释。
你也可以完全通过代码以编程方式构造配置:
JsonObject zkConfig = new JsonObject();
zkConfig.put("zookeeperHosts", "127.0.0.1:2181");
zkConfig.put("rootPath", "io.vertx");
zkConfig.put("retry", new JsonObject()
.put("initialSleepTime", 3000)
.put("maxTimes", 3));
ClusterManager mgr = new ZookeeperClusterManager(zkConfig);
Vertx.builder()
.withClusterManager(mgr)
.buildClustered().onComplete(res -> {
if (res.succeeded()) {
Vertx vertx = res.result();
} else {
// 启动失败!
}
});
可以在 JSON 中自由定制重试策略(Retry Policy):
{
"retry": {
"policy": "exponential_backoff"
}
}
支持的重试策略策略值包括:
-
exponential_backoff(默认:指数退避) -
bounded_exponential_backoff(有上限的指数退避) -
one_time(单次重试) -
n_times(固定 N 次重试) -
forever(持续重试) -
until_elapsed(直到超时)
你还可以通过系统属性 vertx.zookeeper.hosts 快速覆盖 ZooKeeper 服务器连接地址。
|
开启调试日志
在排查 ZooKeeper 集群组网问题时,查看 ZooKeeper 的详细运行时日志非常有帮助。若使用默认的 JUL 日志,可以在类路径下添加 vertx-default-jul-logging.properties 文件,并设置如下级别:
org.apache.zookeeper.level=INFO
同时启用控制台或文件输出处理器:
java.util.logging.ConsoleHandler.level=INFO
java.util.logging.FileHandler.level=INFO