☰
Kafka 2.5.0 安装指南:ZooKeeper 依赖与单机伪集群部署实战
2026/10/14 4:43:51 网站建设 项目流程

1. 为什么现在还有人要装 Kafka 2.5.0

先把话说在前头:Kafka 2.5.0 不是一个新版本,它发布于 2020 年,属于 2.x 系列里比较靠中间的一个版本。放到今天,3.x 甚至 4.x 都已经铺开了,KRaft 模式也在逐步取代 ZooKeeper。那为什么还有人在装 2.5.0?我接触到的真实场景大概有这么几类:一是老项目锁定版本,生产环境跑的就是 2.5.0,本地要搭一套一模一样的来复现问题;二是某些大数据组件生态对 Kafka 客户端版本有硬性依赖,升上去反而会踩兼容性的坑;三是教学和实验环境,2.5.0 的架构足够经典,ZooKeeper 和 Kafka 的关系清晰,适合拿来理解消息队列的底层机制。

所以这篇内容不是教你"追新",而是教你"把 2.5.0 稳稳当当地装起来、跑起来、能验证"。我会从环境准备、ZooKeeper 与 Kafka 的关系、单机与伪集群两种装法、参数配置、启动验证,一直到常见报错排查,完整走一遍。适合谁看?刚接触 Kafka 的运维和开发、需要复现老版本问题的工程师、以及想搞懂 Kafka 到底依赖什么才能跑起来的学习者。哪怕你之前只听过 Kafka 这个名字,跟着走也能装出一套能用的环境。

需要提前说明的是,Kafka 2.5.0 依赖 ZooKeeper 来管理集群元数据,这一点和后来的 KRaft 模式完全不同。你得先接受"要装两个东西"这个前提,后面所有步骤都是围绕这个前提展开的。理解了这一点,很多配置项你就不用死记硬背了。

2. 安装前的整体设计与思路拆解

2.1 为什么 2.5.0 必须搭配 ZooKeeper

Kafka 2.5.0 的架构里,ZooKeeper 承担的是"集群大脑"的角色。它不存消息,消息全在 Kafka 自己的日志文件里,但集群里有哪些 Broker、哪个 Broker 是 Controller、Topic 有多少分区、分区的 Leader 是谁、ISR 列表是什么,这些元数据统统放在 ZooKeeper 里。你可以把 ZooKeeper 理解成一个"通讯录加选举委员会":新 Broker 上线要到它这里登记,Controller 挂了要它来主持重新选举,消费者组的偏移量在早期版本里也存它这儿。

这就决定了安装顺序:先起 ZooKeeper,再起 Kafka。如果 ZooKeeper 没起来,Kafka 启动时会一直报连接超时,日志里刷Connection refused或者Session expired。我见过不少人卡在这一步,以为是 Kafka 配置错了,其实是 ZooKeeper 根本没跑。

那为什么 2.5.0 不自己管元数据?因为 KRaft 模式在 2.5.0 时期还处于早期实验阶段,根本没到能上生产的程度。真正把 ZooKeeper 拿掉是 3.3 之后的事。所以装 2.5.0,你就老老实实把 ZooKeeper 一起装了,别想着绕过。

2.2 单机、伪集群、真集群怎么选

装之前先想清楚你要什么形态,这直接决定配置怎么写。

形态Broker 数量ZooKeeper适用场景配置复杂度
单机模式11本地开发、功能验证低
伪集群31 或 3学习副本机制、模拟故障中
真集群3+3+生产环境高

单机模式最简单,一个 ZooKeeper 加一个 Broker,改几个配置就能跑。伪集群是在一台机器上起多个 Broker 进程,用不同端口区分,主要用来观察分区副本、Leader 选举这些行为。真集群涉及跨机器部署,还要考虑网络、磁盘、机架感知,那是另一个话题了。

我个人的建议是:第一次装,先跑通单机模式,把流程走顺;等单机能稳定收发消息了,再折腾伪集群。一上来就搞三节点,配置一多,出问题你都不知道是哪个环节的锅。

2.3 版本与依赖的取舍逻辑

Kafka 2.5.0 对运行环境有几个硬性要求,这些不是随便定的:

  • JDK 8 或 JDK 11。2.5.0 官方推荐 JDK 8,JDK 11 也支持。别用 JDK 17 及以上,2.5.0 里有些反射相关的代码在新版 JDK 上会因为模块化限制直接报错,比如InaccessibleObjectException。这是很多人踩的坑,装完启动就崩,一看日志是 JDK 版本太高。
  • Scala 2.12 或 2.13。Kafka 是 Scala 写的,2.5.0 提供了两个编译版本,下载包名里带2.12或2.13。选哪个?看你生态里其他组件用什么,一般选 2.12 兼容性更广。
  • ZooKeeper 3.5.x 或 3.4.x。2.5.0 自带的启动脚本可以拉起一个内置的 ZooKeeper,但生产上一般用独立部署的。学习环境用自带的就够。

这里有个细节:Kafka 安装包里其实自带了一个 ZooKeeper,在libs目录下能看到zookeeper-3.5.7.jar之类的文件,bin目录里也有zookeeper-server-start.sh。所以严格来说你不需要单独下载 ZooKeeper,直接用 Kafka 自带的就行。这也是为什么很多人说"装 Kafka 顺便把 ZooKeeper 也装了"。

3. 核心细节解析与实操要点

3.1 环境准备:JDK 和目录规划

第一步永远是环境。先确认 JDK:

java -version

输出应该是1.8.0_xxx或者11.0.x。如果是 17 或更高,先装一个 JDK 8,用update-alternatives或者直接改JAVA_HOME切过去。

目录规划这块,我建议养成习惯,别把东西乱丢。我常用的布局是这样:

/opt/kafka/ # Kafka 安装目录 /opt/kafka/data/ # 消息日志目录,单独放 /opt/zookeeper/ # ZooKeeper 数据目录

为什么把数据目录单独拎出来?因为 Kafka 的消息日志会疯狂增长,如果和安装目录混在一起,哪天磁盘满了你清理起来很麻烦,而且升级 Kafka 时容易误删数据。把log.dirs指向独立目录,升级时只换安装目录,数据原地不动,这是运维的基本素养。

注意:Kafka 的log.dirs里存的不是"日志"(log4j 那种),而是消息数据本身。别被名字骗了,这个目录会非常大,务必挂在大磁盘上。

3.2 下载与解压的正确姿势

2.5.0 的包在官方归档里能找到,文件名类似kafka_2.12-2.5.0.tgz。下载完先校验一下大小,正常在 60MB 上下。解压:

tar -zxvf kafka_2.12-2.5.0.tgz -C /opt/ mv /opt/kafka_2.12-2.5.0 /opt/kafka

解压完看一眼目录结构,心里有个数:

ls /opt/kafka # bin config libs logs site-docs
  • bin:所有启动脚本,包括 Kafka 和 ZooKeeper 的
  • config:配置文件,server.properties和zookeeper.properties都在这
  • libs:所有 jar 包,包括依赖的 ZooKeeper
  • logs:Kafka 自身的运行日志(log4j 输出),不是消息数据

这里要区分清楚:logs目录是 Kafka 进程的运行日志,log.dirs配置指向的才是消息数据。两个"log"含义完全不同,新手最容易搞混。

3.3 ZooKeeper 配置的关键参数

ZooKeeper 的配置文件是config/zookeeper.properties。单机模式下,核心就几个参数:

dataDir=/opt/zookeeper/data clientPort=2181 maxClientCnxns=0 admin.enableServer=false

逐个说:

  • dataDir:ZooKeeper 存快照和事务日志的地方。必须手动创建这个目录,ZooKeeper 不会自动建,目录不存在直接启动失败。
  • clientPort=2181:客户端连接端口,Kafka 就是通过这个端口连上来的。默认 2181,如果被占用要改,改了之后 Kafka 那边也要同步改。
  • maxClientCnxns=0:单个客户端的最大连接数,0 表示不限制。学习环境设 0 省事,生产上要限制防止连接泄漏。
  • admin.enableServer=false:关掉 ZooKeeper 自带的 admin server。这个 admin server 默认占 8080 端口,经常和别的服务冲突,关掉能省不少麻烦。

实操心得:dataDir目录一定要先mkdir -p建好,并且确保运行 Kafka 的用户对这个目录有读写权限。我见过太多"启动就退出"的案例,最后发现是权限问题或者目录不存在。

3.4 Kafka 核心配置逐项拆解

Kafka 的配置文件是config/server.properties。单机模式下,需要改的其实不多,但每一项都得理解:

broker.id=0 listeners=PLAINTEXT://:9092 advertised.listeners=PLAINTEXT://你的机器IP:9092 log.dirs=/opt/kafka/data zookeeper.connect=localhost:2181 num.partitions=1 default.replication.factor=1 offsets.topic.replication.factor=1 transaction.state.log.replication.factor=1 transaction.state.log.min.isr=1
  • broker.id:每个 Broker 的唯一标识,集群里不能重复。单机就 0。
  • listeners:Broker 监听的地址。PLAINTEXT://:9092表示在所有网卡上监听 9092 端口,不加密。
  • advertised.listeners:这个最容易出错。它是 Broker 告诉客户端"你应该用这个地址来连我"的地址。如果只写localhost,那么远程客户端拿到这个地址后连不上。生产环境必须写真实的、客户端能访问到的 IP 或域名。
  • log.dirs:消息数据目录,前面说过,单独放。
  • zookeeper.connect:ZooKeeper 地址,多个用逗号分隔,如zk1:2181,zk2:2181,zk3:2181。
  • num.partitions:新建 Topic 的默认分区数。单机设 1 就行。
  • default.replication.factor:默认副本数。单机只能设 1,设 2 会因为凑不齐副本导致创建 Topic 失败。
  • 后面三个replication.factor相关的:Kafka 内部 Topic(存偏移量、事务状态)的副本配置。单机环境必须都设成 1,否则内部 Topic 创建不出来,消费者根本没法用。

注意:单机环境下,凡是replication.factor相关的参数,统统设成 1。这是新手最容易忽略的地方,设成大于 1 的值,Kafka 启动不报错,但一创建 Topic 就卡住或者报Replication factor: 2 larger than available brokers: 1。

4. 实操过程与核心环节实现

4.1 启动 ZooKeeper 并验证

配置改完,先起 ZooKeeper。前台启动方便看日志:

cd /opt/kafka bin/zookeeper-server-start.sh config/zookeeper.properties

看到日志里出现binding to port 0.0.0.0/0.0.0.0:2181就说明起来了。别关这个终端,另开一个窗口验证:

echo ruok | nc localhost 2181 # 返回 imok 表示正常

ruok是 ZooKeeper 的四字命令,返回imok就代表服务健康。如果nc没装,用telnet localhost 2181也行。这一步很关键,ZooKeeper 没确认好就去起 Kafka,后面出问题你会怀疑人生。

生产环境一般用后台启动:

bin/zookeeper-server-start.sh -daemon config/zookeeper.properties

-daemon会让它后台跑,日志输出到logs/zookeeper.out。

4.2 启动 Kafka Broker

ZooKeeper 确认没问题后,起 Kafka:

bin/kafka-server-start.sh config/server.properties

启动日志里会有一堆信息,重点看这几行:

  • [KafkaServer id=0] started:出现这行才算真正启动成功
  • Registered broker 0 at path /brokers/ids/0:说明 Broker 已经在 ZooKeeper 注册了
  • 如果一直刷Opening socket connection to server localhost/127.0.0.1:2181然后失败,说明 ZooKeeper 没连上

后台启动同理:

bin/kafka-server-start.sh -daemon config/server.properties

启动后验证进程:

jps # 应该能看到 QuorumPeerMain(ZooKeeper)和 Kafka(Kafka Broker)

jps是 JDK 自带的工具,能列出所有 Java 进程。看到这两个就说明两个服务都活着。

4.3 创建 Topic 并验证收发消息

环境起来了,得验证它真能干活。先创建一个 Topic:

bin/kafka-topics.sh --create \ --bootstrap-server localhost:9092 \ --replication-factor 1 \ --partitions 3 \ --topic test-topic

注意 2.5.0 里--bootstrap-server和--zookeeper两种参数都支持。--bootstrap-server是走 Kafka 协议,--zookeeper是直接读 ZooKeeper。新版本推荐用--bootstrap-server,因为--zookeeper在后续版本被废弃了。这里用--bootstrap-server更贴近未来。

查看 Topic 列表和详情:

bin/kafka-topics.sh --list --bootstrap-server localhost:9092 bin/kafka-topics.sh --describe --bootstrap-server localhost:9092 --topic test-topic

describe的输出会显示每个分区的 Leader、Replicas、Isr。单机环境下,三个分区的 Leader 都是 0,Replicas 和 Isr 都是0。

接下来开一个生产者:

bin/kafka-console-producer.sh --bootstrap-server localhost:9092 --topic test-topic

终端会进入等待输入状态,敲几行字回车:

hello kafka second message third message

另开一个终端开消费者:

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test-topic --from-beginning

--from-beginning表示从头消费,不加这个参数只会消费启动之后新产生的消息。你应该能看到刚才输入的三行字被打印出来。到这一步,一套能用的 Kafka 2.5.0 就算装好了。

4.4 伪集群模式的配置差异

如果你想观察副本机制,可以在一台机器上起三个 Broker。核心是复制三份server.properties,改这几个地方:

配置项broker-0broker-1broker-2
broker.id012
listeners:9092:9093:9094
log.dirs/opt/kafka/data-0/opt/kafka/data-1/opt/kafka/data-2
advertised.listenersIP:9092IP:9093IP:9094

三个 Broker 连同一个 ZooKeeper。启动时分别指定不同配置文件:

bin/kafka-server-start.sh -daemon config/server-0.properties bin/kafka-server-start.sh -daemon config/server-1.properties bin/kafka-server-start.sh -daemon config/server-2.properties

然后创建 Topic 时把副本数设成 3:

bin/kafka-topics.sh --create \ --bootstrap-server localhost:9092 \ --replication-factor 3 \ --partitions 3 \ --topic cluster-topic

再用describe看,每个分区的 Replicas 应该是0,1,2这样的组合,Leader 分散在不同 Broker 上。这时候你可以手动 kill 掉一个 Broker,再describe,会看到 Leader 发生了切换,Isr 列表里少了一个。这就是副本机制在起作用,也是伪集群最大的价值——让你亲眼看到故障转移。

实操心得:伪集群启动三个 Broker 很吃内存,每个默认要 1GB 堆。如果机器内存紧张,改bin/kafka-server-start.sh里的KAFKA_HEAP_OPTS,把-Xmx1G调成-Xmx512M。三个加起来 1.5GB,一般开发机扛得住。

5. 常见问题与排查技巧实录

装 Kafka 2.5.0 的过程里,报错基本集中在几个地方。我把踩过的坑整理成一张速查表,遇到问题先对号入座。

现象可能原因排查方向解决方式
Kafka 启动即退出JDK 版本过高看日志有无InaccessibleObjectException换 JDK 8 或 11
一直刷连接 ZooKeeper 失败ZooKeeper 没起或端口不对echo ruok | nc localhost 2181先起 ZooKeeper,核对端口
创建 Topic 报副本数过大单机设了 replication.factor>1看default.replication.factor改成 1
消费者收不到消息没加--from-beginning确认消费起始位置加参数或先发新消息
远程客户端连不上advertised.listeners 是 localhost检查该配置改成真实 IP
启动报 dataDir 不存在ZooKeeper 数据目录没建看 zookeeper.propertiesmkdir -p建目录
端口被占用9092 或 2181 被别的进程占了netstat -tlnp | grep 9092改端口或杀进程

5.1 JDK 版本导致的启动崩溃

这个坑我踩过不止一次。现象是执行kafka-server-start.sh后,进程起来几秒就没了,日志里一堆java.lang.reflect.InaccessibleObjectException。原因是 JDK 9 之后引入了模块系统,对反射访问做了限制,而 Kafka 2.5.0 里有些代码用了反射去访问 JDK 内部类。

解决办法就一个:换 JDK 8。别想着加--add-opens参数去绕过,2.5.0 涉及的反射点比较多,一个个加参数不现实,而且容易漏。直接切 JDK 8 最省心。切换方式:

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export PATH=$JAVA_HOME/bin:$PATH

确认java -version输出是 1.8 再启动。

5.2 ZooKeeper 连接超时的排查链路

Kafka 启动卡在连 ZooKeeper 上,排查要按顺序来:

  1. 先确认 ZooKeeper 进程在不在:jps | grep QuorumPeerMain
  2. 再确认端口通不通:nc -zv localhost 2181
  3. 然后确认server.properties里的zookeeper.connect地址对不对
  4. 最后看 ZooKeeper 日志有没有报错

这四步走下来,基本能定位。最常见的是 ZooKeeper 根本没起来,或者dataDir目录不存在导致 ZooKeeper 自己启动失败。ZooKeeper 启动失败时,日志在logs/zookeeper.out,里面会写清楚原因。

5.3 内部 Topic 创建失败的隐蔽问题

这个坑比较隐蔽。Kafka 启动看起来正常,但消费者一启动就报错,或者__consumer_offsets这个内部 Topic 一直创建不出来。根源是offsets.topic.replication.factor设成了大于 Broker 数量的值。

Kafka 内部有三个关键 Topic:__consumer_offsets(存消费者偏移量)、__transaction_state(存事务状态)。它们的副本数由offsets.topic.replication.factor和transaction.state.log.replication.factor控制。单机环境如果这俩设成 2 或 3,Kafka 会一直尝试创建但永远凑不齐副本,导致消费者无法提交偏移量。

解决方式就是前面配置里说的,单机统统设 1。这个问题的恶心之处在于它不报明显错误,只是"消费者不工作",新手很难联想到是内部 Topic 的问题。

5.4 磁盘写满与日志清理

Kafka 的消息数据默认保留 7 天(log.retention.hours=168),过期自动删。但如果你测试时疯狂发消息,7 天没到磁盘就满了。这时候要手动清理或者调整保留策略。

调整保留时间:

log.retention.hours=24 log.retention.bytes=1073741824

log.retention.bytes限制单个分区最大占用,超过就删旧数据。测试环境建议设小一点,比如 1GB。

手动删除某个 Topic 的数据:

bin/kafka-topics.sh --delete --bootstrap-server localhost:9092 --topic test-topic

注意 2.5.0 里删除 Topic 需要delete.topic.enable=true(默认就是 true)。删除是异步的,执行完不会立刻消失,等一会儿再--list就看不到了。

实操心得:测试环境我习惯把log.retention.hours设成 1,log.retention.bytes设成 512MB。这样即使忘了清理,磁盘也不会被撑爆。生产环境另说,要根据数据量和磁盘容量算。

6. 装完之后还能做点什么

环境跑通只是起点。如果你想让这套 2.5.0 发挥更大价值,可以往几个方向延伸。一是用kafka-consumer-groups.sh观察消费者组的偏移量、lag 情况,理解消费进度的管理;二是故意 kill 掉 Broker 观察 Controller 重新选举的过程,加深对集群协调机制的理解;三是用kafka-run-class.sh配合kafka.tools.GetOffsetShell之类的工具,直接查分区的偏移量范围。

我个人在实际操作中的体会是,Kafka 2.5.0 这套 ZooKeeper 架构虽然"老",但它把分布式协调的很多概念暴露得很直白。你装一遍、配一遍、故意搞坏一遍再修好,对消息队列的理解会比单纯看文档深得多。尤其是伪集群那部分,三个 Broker 起起停停,Leader 切来切去,那种"原来副本是这么工作的"的感觉,是看多少篇文章都换不来的。

最后再分享一个小技巧:把启动和停止命令写成脚本,省得每次敲一长串。比如建一个start-all.sh,里面按顺序起 ZooKeeper 和 Kafka,再建一个stop-all.sh反着停。停的时候先停 Kafka 再停 ZooKeeper,顺序反了 Kafka 会因为找不到 ZooKeeper 报一堆错,虽然不影响数据,但日志很难看。养成这个习惯,日常折腾效率能高不少。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询