问题描述
背景
我维护一个环境,该环境托管 Java Spring 应用程序的实例以及一个 3 节点的 Apache Zookeeper 集成来存储用户特定的数据。用户运行他们自己的应用程序实例,但每个实例都连接到共享的 Zookeeper 集合。为了分离数据,每个实例都配置了自己的子目录,以便在 Zookeeper 中 chroot 该实例。完整的 Zookeeper 节点结构如下所示:
- /
- UserA
- Dir1
- File1
- File2
- Dir2
- File3
- File4
- UserB
- Dir1
- File1
- File2
- Dir2
- File3
- File4
- UserC
- Dir1
- File1
- File2
- Dir2
- File3
- File4
服务器配置文件类似于:
zkserver1,zkserver2,zkserver3/UserA
因此,UserA 的应用程序通过 Apache Curator 客户端连接到 Zookeeper,并且只能看到它们的目录结构:
- /
- Dir1
- File1
- File2
- Dir2
- File3
- File4
该应用程序使用 Apache Curator 框架来简化 Zookeeper 访问。 Spring 将此 Curator 客户端作为单例注入到应用程序的多个组件中。由于每个组件共享同一个实例,它们都具有相同的服务器数据和来自配置文件的 chroot 路径。
问题
当 Zookeeper ensemble 失去其法定人数(即三个服务器中的两个停止)然后重新建立健康的法定人数(回到三个连接的服务器)时,一些使用 Curator Zookeeper 客户端的组件“失去了知识” chroot 路径。在此 Zk 循环之前,用户 A 可以检查路径为 /Dir2/File3
(绝对路径 /UserA/Dir2/File3
)的节点“File3”的存在并接收 true
。在 Zk 循环之后,/Dir2/File3
返回 false
,因为没有预先添加 chroot 路径 /UserA
- Zookeeper 检查的绝对路径是 /Dir2/File3
并且不存在。>
令人困惑的是,应用程序的其他组件在 Zookeeper 循环之后工作正常。它们使用相同的单例 Curator ZkClient、相同的服务器和 chroot 配置等。
问题排查
由于公司 IP 规则,我无法在此处发布组件源代码,但可以详细说明我是如何解决此问题的。
到目前为止,我已经
- 通过直接查询 Curator 持有的 Zookeeper 客户端对象来消除 Curator。
- 通过使用 python 脚本和 Kazoo 库监控文件结构,排除了 Zookeeper 节点的不稳定。
- 在工作和非工作组件之间转换代码,并从 Zookeeper 收到相同的结果。
- 在工作/非工作组件 REST 控制器之间注入组件 bean,并从 Zookeeper 收到相同的结果。
- 如果 Curator ZkClient 的连接状态为 RECONNECTED,则通过预先设置用户的 chroot 路径,验证每个组件所需的数据仍可访问。
归根结底,这比实际问题更令人烦恼,但我仍然想解决这个问题。如果您有任何新的故障排除方法或有关 Zookeeper 客户端已知问题的任何信息,我将不胜感激。
编辑/解决方案
这个问题在 Zookeeper 3.6.2(我尝试过的最新版本)中似乎不存在。发行说明似乎没有提到 chroot 问题,但我设置的一个有限测试展示了所需的行为,而不是复制这个问题。
如果您需要测试 Zookeeper 版本,Docker Hub 上的 zookeeper page 描述了如何让它运行。
我无法让三节点集成正确通信以进行领导者选举,但您也可以使用此 docker compose 文件运行单节点集成:
services:
zoo1:
image: zookeeper:[version num]
restart: always
hostname: zoo1
ports:
- 2181:2181
- 2888:2888
- 3888:3888
environment:
ZOO_MY_ID: 1
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)