ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ZooKeeper 3.8.5单节点一键安装Bash脚本与配置详解

ZooKeeper 3.8.5单节点一键安装Bash脚本与配置详解 作为长期和 ZooKeeper、Hadoop 打交道的工程师我经常要在干净的环境里快速搭一套单节点 Zookeeper 3.8.5 出来做开发自测或者教程演示。手动敲命令不是不行但装多了就会发现来回下载解压、改 zoo.cfg、写 myid、配权限哪个环节都容易手滑。这篇文章就直接把我常用的单节点 Zookeeper 3.8.5 一键安装 Bash 脚本完整贴出来重点不光是给你脚本而是把脚本里每一段命令背后的逻辑、每个配置项的含义以及我在多台服务器上踩过的坑都讲清楚。如果你刚接触 Zookeeper想在自己的笔记本或云主机上快速跑起来或者你是运维需要在隔离环境里部署一个给 Kafka、Hadoop、Dubbo 做注册中心和协调服务的节点这篇文章都适用。单节点虽然不满足生产高可用要求但作为学习、开发、联调环境它绰绰有余。我的目标很简单你拿到这个脚本跑完就能用并且知道出了问题去哪查。1. 为什么我选择脚本安装而不是 Docker 镜像1.1 单节点 ZooKeeper 到底解决什么问题ZooKeeper 在分布式系统里干的事情说白了就是三件分布式协调、配置管理和命名服务。很多人第一次接触它是因为 Hadoop 或者 Kafka 的依赖需要先有一个能连的 ZooKeeper 地址。这种情况下单节点部署是性价比最高的选择。单节点的特点也很明确一台机器一个 JVM 进程数据只存在本机没有 leader 选举和数据同步的烦恼。它非常适合以下几类场景本地开发调试你在电脑上写代码需要一个真实的 ZooKeeper 连一下而不是用内存版 mock。测试环境联调团队共用的测试服务器上给下游服务提供一个稳定的注册中心。学习原理想看看 Zab 协议、zk 的数据模型、watch 机制单节点完全够看。搭建临时演示环境比如我写文章时用的就是这个方式。换个角度说单节点没有高可用能力进程一挂服务就断了。所以生产环境至少三节点起步这个结论在后面的章节我还会再强调。1.2 不用 Docker 的原因你可能会问现在容器化这么方便为什么不直接用 docker run zookeeper:3.8我在一些场景下确实会用 Docker但对于“一键安装”这个目标脚本往往比容器更顺手有些服务器在内网环境外网访问受限镜像仓库根本拉不下来反而 archive.apache.org 的安装包可能已经有缓存。容器网络和宿主机网络的端口映射在部分定制化系统上会引入额外复杂度不如直接跑原生进程来得直观。开发测试时如果你需要看 JVM 的完整线程栈、做 jmap 分析原生进程比容器里操作少一层障碍。脚本安装更容易融入企业现有的配置管理规范比如统一目录、统一用户、统一日志清理策略。不是说容器不好而是脚本更符合“可控、可审计、可重复执行”这三个需求。我把这个脚本放到 Git 仓库里以后任何一台新机器 clone 下来跑一遍就能得到同样环境这就是一键脚本比手工敲命令最大的价值。1.3 为什么锁定 Zookeeper 3.8.5 这个版本Zookeeper 3.8.x 是 Apache ZooKeeper 的一个相对新的稳定分支相比老的 3.4/3.5 系列它在安全、性能、可观测性方面都有了不少改进。3.8.x 默认支持 Java 8/11/17而且修复了多个 CVE 问题官方也一直在积极维护。版本锁定成 3.8.5 而不是直接用 latest原因很简单生产环境最忌讳的运维操作就是频繁升级。同一个项目里如果所有服务器都用同一个小版本就不会出现版本之间协议差异或端口行为不一致的问题。我见过不少团队在 ZooKeeper 版本上吃过亏一台 3.4一台 3.6客户端用 3.8 的客户端库连上去结果发现某些 API 行为不一致。所以脚本里我把版本写死成变量 ZK_VERSION3.8.5想换版本修改一处就行。2. 安装前必须想清楚的三个设计问题2.1 目录规划软件、数据、日志要分开我给这个脚本定的目录规划是这样的安装目录/opt/apache-zookeeper-3.8.5-bin并创建软链接 /opt/zookeeper 指过去数据目录/data/zookeeper日志目录/data/zookeeper/logs为什么要分开最直接的原因是重装和升级。如果数据和软件放在同一目录升级时一个 rm -rf 就把数据全清了。而把数据目录指向 /data 这样的独立分区升级版本时只要软链接换一下数据原封不动。另一个原因是磁盘性能。ZooKeeper 的 TPS 瓶颈主要在磁盘 I/O尤其事务日志需要持续写入如果 /opt 所在盘是机械盘而 /data 是 SSD目录分离就能把日志放到 SSD 上性能差异非常大。脚本目录结构上还有一个容易忽略的点数据目录最好不用 ZooKeeper 安装目录下的默认子目录。3.8 的 bin 安装包自带 conf/data 这样的相对目录但相对目录在服务启动时很容易受当前工作目录影响导致数据位置飘忽不定。所以我在脚本里全部使用了绝对路径这是经验之谈。2.2 用户隔离为什么用独立的 zookeeper 用户安装脚本里我特意创建了一个名为 zookeeper 的系统用户而不是直接使用 root 来启动服务。JVM 进程如果以 root 运行一旦应用本身有漏洞攻击者拿到的是整个 root shell而用低权限用户运行即使被入侵影响面也小得多。这个习惯在部署任何中间件时都适用像 Elasticsearch、Kafka 官方也都有类似要求。ZooKeeper 的一家老小——数据和日志目录也全部 chown 给 zookeeper 用户。这样做的原因是即使你在脚本中是用 root 装的之后日常运维中比如手动执行 zkServer.sh也要以 zookeeper 用户来操作防止 root 创建的目录让普通用户没有写权限。2.3 脚本设计的核心原则幂等性和可重复执行一个合格的安装脚本必须能反复跑不出错。我第一次写部署脚本时吃了大亏解压这一步没有判断目录是否已存在第二次执行时报错“文件已存在”。所以这个脚本在下载解压前先判断安装目录是否已经存在如果存在就跳过解压只更新配置和启动服务。同样myid 文件的写入也做了幂等处理每次都直接 echo 1 覆盖不会追加成多行。数据目录和日志目录用 mkdir -p 确保没有不存在的问题。这套思路对运维来说非常实用你不需要担心脚本跑了一半失败后第二次从头执行会不会有脏状态。3. 完整安装脚本与逐段拆解3.1 先看完整的 Bash 脚本下面就是我现在常用的脚本适用于 CentOS 7/8、Ubuntu 20.04/22.04 等常见 Linux 发行版前提是你已经装好了 Java 环境版本 8 以上即可。我默认是以 root 用户或 sudo 权限执行因为脚本内部需要创建用户和修改 /opt、/data 目录。#!/usr/bin/env bash set -euo pipefail ZK_VERSION${ZK_VERSION:-3.8.5} BASE_DIR${BASE_DIR:-/opt} DATA_DIR${DATA_DIR:-/data/zookeeper} LOG_DIR${LOG_DIR:-/data/zookeeper/logs} CLIENT_PORT${CLIENT_PORT:-2181} log() { echo -e \033[1;32m[INFO]\033[0m $* } warn() { echo -e \033[1;33m[WARN]\033[0m $* } fail() { echo -e \033[1;31m[ERROR]\033[0m $* exit 1 } # 0. 前置检查 [[ $EUID -ne 0 ]] fail 请使用 root 用户或 sudo 执行本脚本 command -v curl /dev/null 21 || fail 未找到 curl请先安装 command -v tar /dev/null 21 || fail 未找到 tar请先安装 command -v java /dev/null 21 || fail 未找到 javaZookeeper 3.8 需要 Java 8 command -v nc /dev/null 21 || warn 未找到 nc健康检查步骤会使用 /dev/tcp 代替 # 1. 创建专用用户 if ! id zookeeper /dev/null 21; then useradd -r -s /usr/sbin/nologin zookeeper log 已创建系统用户 zookeeper fi # 2. 下载解压 BIN_URLhttps://archive.apache.org/dist/zookeeper/zookeeper-${ZK_VERSION}/apache-zookeeper-${ZK_VERSION}-bin.tar.gz INSTALL_DIR${BASE_DIR}/apache-zookeeper-${ZK_VERSION}-bin if [[ ! -d ${INSTALL_DIR} ]]; then log 开始下载 ${BIN_URL} curl -fSL ${BIN_URL} -o /tmp/zk.tar.gz tar -xzf /tmp/zk.tar.gz -C ${BASE_DIR} rm -f /tmp/zk.tar.gz [[ -d ${INSTALL_DIR} ]] || fail 解压失败可能下载包不完整 fi ln -sfn ${INSTALL_DIR} ${BASE_DIR}/zookeeper # 3. 创建数据目录 mkdir -p ${DATA_DIR} ${LOG_DIR} chown -R zookeeper:zookeeper ${DATA_DIR} ${LOG_DIR} chown -R zookeeper:zookeeper ${INSTALL_DIR} # 4. 写 myid echo 1 ${DATA_DIR}/myid chown zookeeper:zookeeper ${DATA_DIR}/myid # 5. 生成 zoo.cfg cat ${INSTALL_DIR}/conf/zoo.cfg EOF tickTime2000 initLimit10 syncLimit5 dataDir${DATA_DIR} dataLogDir${LOG_DIR} clientPort${CLIENT_PORT} maxClientCnxns60 admin.enableServerfalse 4lw.commands.whitelistsrvr,ruok,mntr,conf,stat autopurge.snapRetainCount3 autopurge.purgeInterval1 EOF chown zookeeper:zookeeper ${INSTALL_DIR}/conf/zoo.cfg log zoo.cfg 已生成 # 6. 启动服务 log 准备启动 Zookeeper su -s /bin/bash zookeeper -c ${INSTALL_DIR}/bin/zkServer.sh start # 7. 端口健康检查 for i in {1..30}; do if (exec 3/dev/tcp/127.0.0.1/${CLIENT_PORT}) 2/dev/null; then exec 3- 3- break fi sleep 1 done if (exec 3/dev/tcp/127.0.0.1/${CLIENT_PORT}) 2/dev/null; then exec 3- 3- log 端口 ${CLIENT_PORT} 已就绪 else warn 端口 ${CLIENT_PORT} 未就绪请检查日志 fi echo log Zookeeper ${ZK_VERSION} 安装完成 log 安装目录${INSTALL_DIR} log 数据目录${DATA_DIR} log 客户端连接127.0.0.1:${CLIENT_PORT} log 状态查看echo srvr | nc 127.0.0.1 ${CLIENT_PORT}3.2 前置检查为什么 set -euo pipefail 和命令检测那么重要脚本开头我写了set -euo pipefail这一行对安装脚本来说价值巨大。简单解释一下-e表示任何一条命令返回非零状态就立刻退出避免在错误状态下继续执行-u表示使用未定义变量直接报错防止手滑打错变量名-o pipefail则保证管道中任何一个环节出错整个管道命令就失败。很多新手会忽略管道中前面命令报错后面命令照样执行导致的“假成功”这个参数可以避免。接下来我依次检查了 curl、tar、java、nc 这几个命令是否存在。curl 负责下载tar 负责解压java 是 ZooKeeper 运行的根本nc 用于四字命令检测。如果这些基础工具缺了安装过程会以极其诡异的方式失败比如下载了却解不开解开了却 JVM 报错。与其让用户在一堆日志里找原因不如前置检查那里就明确提示。这里有个小细节nc 不是每个发行版都会预装。所以我对待 nc 只给了 warn 而不是 fail因为脚本后续的健康检查使用的是 /dev/tcp 这个 Bash 内置能力即使没有 nc 也能完成端口探测。但如果你需要执行 srvr 等四字命令检查最后还是建议装上 nc方法在后文会有说明。3.3 下载解压为什么一定要用带 bin 后缀的包下载包名是 apache-zookeeper-3.8.5-bin.tar.gz这个 bin 后缀非常关键。Apache ZooKeeper 的发布页有两种包一种是源码包需要自己用 Maven 编译解压后没有 bin/zookeeper-server-start.sh 这种可直接执行的脚本另一种是二进制包自带编译好的 class 文件和启动脚本。你安装服务一定选择带 -bin 的版本否则折腾半天最后发现连启动脚本都没有。下载后我用 curl -fSL。-f表示 HTTP 请求失败就直接报错而不是生成一个错误页面文件-S显示错误信息-L表示跟随 301/302 跳转。archive.apache.org 经常会有跳转没有 -L 的话 curl 通常会失败或者在本地生成一个 redirect 数据文件。这个坑我在老版本的脚本里踩过一次后来凡是下载动作都默认加上 -L。解压后为什么会校验一下${INSTALL_DIR}是否存在因为在某些网络环境里下载可能到了 99% 突然断开然后 curl 因为 -f 会报错退出吗其实不一定某些代理场景下会留下残缺文件。我加了一个显式判断如果目录不存在直接提示包不完整省得用户去猜为什么启动脚本找不到了。3.4 生成 zoo.cfg几个参数我为什么这么配zoo.cfg 是整个 ZooKeeper 安装的核心配置文件。我在脚本里用了 heredoc 一次性写入完整的配置下面逐个解释tickTime2000这是 ZooKeeper 使用的基本时间单元单位毫秒。它决定了会话心跳的间隔默认 2000 毫秒。一般场景不需要改动除非你的网络延迟特别高想放宽超时时间。initLimit10 和 syncLimit5这两个参数在单节点下其实不生效它们分别用于 follower 启动时连接 leader 的超时时间以及 follower 与 leader 之间的通信超时。我保留这个配置是为了以后扩容方便加几台机器改成集群时不用再修改配置。dataDir 和 dataLogDir前面说过的数据隔离这里就是实际落地的位置。dataDir 存快照文件和 myiddataLogDir 存事务日志。两个目录要提前用 mkdir -p 创建ZooKeeper 不会自动创建目录这是非常容易踩的坑。maxClientCnxns60限制单个客户端 IP 的最大连接数。默认 3.5 版本以上这个值是 0表示不限制。我显式设置为 60是防止有问题的客户端代码疯狂重连把连接池打满导致正常客户端被拒。admin.enableServerfalse关闭 8080 端口的 Admin Server。3.5 版本开始 ZooKeeper 默认会启动一个 HTTP 管理端在 8080 端口但很多服务器上 8080 早被别的应用占了。如果你不需要那个 Web 界面就直接关掉需要的话可以改成 admin.serverPort8888 换端口。4lw.commands.whitelistsrvr,ruok,mntr,conf,stat这个必须有。3.5 开始 ZooKeeper 出于安全考虑默认不开启四字命令。四字命令指的是用 echo srvr | nc localhost 2181 这样的方式查看服务器状态。如果不加这个白名单ruok 永远没有响应很多人会以为 ZooKeeper 挂掉了实际上只是被白名单拦了。autopurge.snapRetainCount3 和 autopurge.purgeInterval1自动清理快照和事务日志。ZooKeeper 在持久化时会产生大量 data 目录文件如果不清理时间久了磁盘会被撑爆。snapRetainCount 表示保留最近 3 份快照purgeInterval 表示每 1 小时检查并清理一次。3.5 启动和健康检查为什么我不直接裸跑 Java 命令启动步骤用了官方的 zkServer.sh 脚本这个脚本会读取 conf/zoo.cfg设置 JVM 参数并且把进程 pid 记录到 zookeeper_server.pid 文件。用手工 java -cp 方式启动虽然也能跑但你要自己处理 classpath、JVM 参数、pid 文件等一堆琐事完全没有必要。我用 su -s /bin/bash zookeeper -c 来切换用户是考虑到有些系统没有 sudo 或者配置不正确。su 这个命令在几乎所有 Linux 上都存在用 -s 指定 shell 是为了避免 nologin 用户无法执行的问题。启动之后的健康检查用的是 Bash 的 /dev/tcp 网络探活方式。命令逻辑是尝试与 127.0.0.1:2181 建立一个 TCP 连接如果能建立就说明端口已经进入监听状态测试连接后立即关闭。为什么要循环 30 次因为 JVM 启动需要时间尤其是第一次启动要加载类库、初始化数据库可能 2 到 3 秒后才能完成端口监听。每次循环 sleep 1 秒最多等待 30 秒这个范围足够覆盖绝大多数情况。这里有个细节连接断开用的是exec 3- 3-把文件描述符 3 正确关闭。如果不关这个脚本会一直持有端口连接后续其他进程连接会被占用甚至影响 ZooKeeper 的连接数统计。类似的小问题在网络上很多人写过但很少有博客提到。4. 安装完成后的验证和进阶配置4.1 用四字命令和 jps 双重确认服务状态脚本执行成功后第一件事就是确认真实状态。我常用的三条命令如下echo srvr | nc 127.0.0.1 2181 echo ruok | nc 127.0.0.1 2181 jpssrvr 会返回该节点的角色、版本、连接数等信息ruok 在正常状态下返回 imok。jps 是 JDK 自带工具能列出当前用户启动了哪些 Java 进程你应该能看到一个名为 QuorumPeerMain 的进程这个就是 ZooKeeper 的主类。如果你执行这些命令时发现没有响应最可能的原因是配置文件缺少 4lw.commands.whitelist。这个坑我放在第 5 章详细讲。另外我也建议你在项目里加一个 Java 客户端的最小连接测试用 Java 代码或者用命令行工具 zkCli.sh 连一下/opt/zookeeper/bin/zkCli.sh -server 127.0.0.1:2181进入 zkCli 交互界面后执行ls /如果能看到一份默认 zookeeper 节点列表说明业务层面已经通透了。这个测试比单纯 ping 端口更真实因为客户端协议握手成功才能返回正常结果。4.2 用 systemd 托管进程让随机重启更省心脚本里直接用 zkServer.sh start 启动这种方式在手动维护时没问题但有一个很大的隐患服务器重启后 ZooKeeper 不会自动启动。如果需要开机自启我强烈建议给 ZooKeeper 配置一个 systemd 服务。下面这个 unit 文件可以直接用路径根据自己的 ZK_HOME 调整[Unit] DescriptionApache ZooKeeper Server Documentationhttps://zookeeper.apache.org Afternetwork.target [Service] Typeforking Userzookeeper Groupzookeeper EnvironmentZOO_LOG_DIR/data/zookeeper/logs ExecStart/opt/zookeeper/bin/zkServer.sh start ExecStop/opt/zookeeper/bin/zkServer.sh stop ExecReload/opt/zookeeper/bin/zkServer.sh restart PIDFile/opt/zookeeper/data/zookeeper_server.pid Restarton-failure RestartSec10 [Install] WantedBymulti-user.targetPIDFile 的路径要特别注意。zkServer.sh 默认把 pid 写在 dataDir 下面如果你改了 dataDirpid 路径也会跟着变。systemd 里如果路径写错stop 和 restart 功能会失效。我第 5 章会提到实际案例。4.3 留给 Hadoop / Kafka 整合的提醒这个脚本搭建的单节点 ZooKeeper常被用来配合 Hadoop 或 Kafka。如果是给 Hadoop HA 使用的要注意 ZooKeeper 需要开启 2888 和 3888 端口单节点同样要开放因为 NameNode 的 Active/Standby 切换依赖 ZooKeeper 会话。脚本里的 zoo.cfg 其实没配置这两个端口的监听单节点下不需要但如果你将来要扩成三节点集群千万记得在 zoo.cfg 补上类似下面的配置server.1192.168.1.10:2888:3888 server.2192.168.1.11:2888:3888 server.3192.168.1.12:2888:3888如果是配合 Kafka注意 Kafka 客户端默认的 session timeout 是 10s而单节点 ZooKeeper 没有选举过程响应很快一般不会出问题。但我建议你在那台 Kafka 机器的 clientPort 压力下观察一下 maxClientCnxns 是否够用通过 srvr 命令能看到当前连接数。5. 常见问题与排查技巧实录5.1 一张速查表解决大部分问题我把实际运维中碰到过的高频问题整理成一个表按照“现象-排查-解决”的思路来写你遇到问题可以先对号入座。现象可能原因排查与解决端口 2181 没监听JVM 启动失败多半是 Java 版本太低或内存不够看 logs/zookeeper.log确认 java -version检查系统可用内存ruok 没有任何响应4lw.commands.whitelist 未配置或漏了 ruok在 zoo.cfg 里加上白名单重启服务启动报 Unable to load databasedataDir 里残留了旧版本数据或者 myid 格式不对确认 dataDir 指向正确备份后清理目录重建 myid连接超时防火墙未放行 2181或客户端配置的 server 地址不可达检查 telnet 2181确认网络与防火墙策略8080 端口被占admin.server 默认端口冲突在 zoo.cfg 设 admin.serverPort 或直接 admin.enableServerfalsesystemd stop 失败PIDFile 路径配置与 dataDir 不一致查看 data/zookeeper_server.pid 真实位置并同步到 unit 文件磁盘空间不断上涨autopurge 没开或 purgeInterval 设置太大确认 autopurge.snapRetainCount 和 purgeInterval 配置生效内存占用过高JVM 堆设置过大比如默认的 Xmx1000m 在低配机器上占比高在 conf/java.env 中统一定制 JVM 参数表格里列的这些基本覆盖了我遇到过 90% 的安装类故障。剩下 10% 大多和操作系统本身有关比如 SELinux 拦截端口绑定或者 ulimit 限制导致打开文件数不够。遇到这种问题先打开日志认认真真从头读别靠猜。5.2 最隐蔽的坑四字命令无响应我说这个坑隐蔽是因为它不会影响 ZooKeeper 本身的正常服务客户端连接写数据都没问题但只要你想看状态就会发现 echo ruok | nc 127.0.0.1 2181 回车后毫无反应。很多人在这时候就开始猜是不是服务挂了然后重启结果重启完还是一样。问题其实在 3.5 版本以后的安全策略上。官方默认把四字命令的白名单收紧了如果没有显式配置 4lw.commands.whitelistruok、stat、conf 这些命令都不生效。我在脚本里已经配好了但如果你手写配置文件忘记这一行的概率非常高。经验是只要碰到四字命令无响应第一件事看 zoo.cfg 里有没有这行而不是重启服务。如果你想全部开放可以粗暴地写4lw.commands.whitelist*但这等于把所有内网敏感的调试接口都暴露了我不建议这么干。按需放行常用命令是最稳妥的我就是按 srvr,ruok,mntr,conf,stat 选了个最小集。5.3 多版本升级时的数据兼容假设以后官方出了 3.9你想从 3.8.5 升上去。千万不能直接拿新版本启动旧 dataDir 里的数据。ZooKeeper 的数据文件有版本兼容性问题虽然不是每次都出问题但升级前一定要完整备份 dataDir并且先在新版本上用相同 dataDir 做一次试启动确认日志中没有异常再切换正式服务。我的做法是先把旧版本进程停止接着把 dataDir 整个复制到一个临时目录例如 /data/zookeeper_backup_3.8.5然后用新版本 bin 包的 zkServer.sh start 指向原数据目录盯紧日志输出。如果客户端业务验证正常并且 srvr 返回的 zxid 没有异常回退就说明升级成功。整个过程最好安排在业务低峰期操作即使单节点环境也一样。5.4 日志文件怎么翻才高效ZooKeeper 的日志默认写在 conf/zoo.cfg 所在位置的相对路径正常情况下会输出到 dataDir 或者你指定的 ZOO_LOG_DIR。这个脚本里我没有显式设置 ZOO_LOG_DIR所以默认记录在安装目录的 logs 子目录下也就是 /opt/apache-zookeeper-3.8.5-bin/logs/zookeeper.log。这个文件是最主要的排障入口。翻日志的时候我建议你直接搜关键词 WARN 和 ERROR先定位异常时间点再往前看几行找根因。有一个比较典型的日志片段ERROR Unexpected exception causing shutdown to occur后面通常会跟着栈信息。如果是 OutOfMemoryError基本可以确定是 JVM 堆内存给小了可以通过 ZK_SERVER_HEAP 环境变量来调大比如设置成 512m 或 1g。调 JVM 这种需求我会在安装目录下创建一个 java.env 文件这个是 zkServer.sh 默认会加载的 JVM 参数配置文件。例如写到export ZK_SERVER_HEAP1024 export ZK_SERVER_JVMFLAGS-Xmx1024m -Xms1024m修改后重启 ZooKeeper就能看到内存参数生效了。对于一台只有 2G 内存的虚拟机来说512m 和 1g 的差别还是很大的别上来就设 4g。6. 实际使用过程中的额外经验脚本跑通只是第一步真正让它好用地顺滑还需要一些使用习惯上的补充。我后来的部署实践中几乎都会把 systemd unit 文件补充进去所以在 4.2 节里专门给了样例。这也是我踩过几次坑后总结出来的很多云主机的自动伸缩或者镜像重建功能会直接重启操作系统如果你没配 systemdZooKeeper 就静静躺在那儿等你发现业务连不上再去手动启动整个过程被拿捏得很难受。另外关于客户端连接串我建议把所有需要连接 ZooKeeper 的应用统一配置成 127.0.0.1:2181 或实际服务器的内网 IP。不要使用 localhost。因为在某些云环境和容器网络里localhost 解析可能指向 IPv6 地址而 ZooKeeper 默认只监听在 IPv4 上两边一对不上连接直接超时。这类问题非常隐蔽排障的时候容易绕弯。如果你手头这台机器还有 Kafka 同时运行还要注意 CPU 和内存的分配。ZooKeeper 和 Kafka 都是 JVM 进程Kafka 本身非常吃内存两者叠加在小机器上容易触发 OOM。我最开始在一台 4G 内存虚拟机里同时跑事务密集的测试业务ZooKeeper 反复崩溃查了半天才意识到是内存不够。后来单独部署到不同机器才彻底解决。最后还想提一个小技巧脚本执行完以后第一件事去 /data/zookeeper 目录看有没有 version-2 文件夹。ZooKeeper 会自动创建这个目录来存放持久化快照。如果执行完还没有很可能说明进程没有正确启动这时候不要急着连客户端先看日志里是否报错“dataDir 创建失败”或“权限不足”。能把数据目录真正初始化成功才是安装完成的最本质标志。就我自己的体验来说单节点 ZooKeeper 本身就是个很轻量的服务动手安装一次之后后面再装十次都不会觉得难。脚本不是万能的真正让你少走弯路的是理解每个参数和每一步操作背后的原因。这个脚本放在我的部署仓库里每次交付新环境直接跑一遍输出稳定心里踏实。如果你照着它部署成功了后续再往三节点集群扩的时候把 zoo.cfg 的 server 列表补齐就行前面的基础架构不用推倒重来。
返回列表