3、环境准备:Kafka集群搭建与监控配置

说实话,很多人在MirrorMaker上栽跟头,不是因为工具本身多难,而是环境没搭好。源集群和目标集群的配置差异、网络不通、监控缺失——这些问题一旦埋下,后面排查起来非常痛苦。我自己的习惯是,先把环境做到“可观测、可复现”,再开始搞复制任务。

这一章,我们就一步步把两个Kafka集群搭起来,把网络打通,再把JMX监控挂上。嗯,都是基础活,但基础不牢,地动山摇。

3.1 集群规划:先想清楚再动手

我个人建议,源集群和目标集群最好用相同的Kafka版本。跨大版本复制虽然也能跑,但有些内部协议变化会带来奇怪的问题。我曾经遇到过源集群2.8、目标集群3.4的情况,结果MirrorMaker在同步Offset时频繁报错,最后统一版本才消停。

下面是我常用的一个最小化规划方案,适合实验环境或小规模生产:

角色 节点 Broker ID ZooKeeper 监听端口
源集群 node-1 101 zk1:2181/source 9092
源集群 node-2 102 zk1:2181/source 9092
源集群 node-3 103 zk1:2181/source 9092
目标集群 node-4 201 zk2:2181/target 9092
目标集群 node-5 202 zk2:2181/target 9092
目标集群 node-6 203 zk2:2181/target 9092

注意ZooKeeper的chroot路径。源集群用/source,目标集群用/target,这样即使共用同一套ZK集群,数据也不会混淆。你想想看,如果两个集群的元数据写在同一个ZK路径下,那画面太美我不敢看。

3.2 搭建源集群

以node-1为例,其他节点类似。我习惯把Kafka解压到/opt/kafka,然后通过软链管理版本。

# 下载并解压(版本以3.5.0为例)
wget https://downloads.apache.org/kafka/3.5.0/kafka_2.13-3.5.0.tgz
tar -xzf kafka_2.13-3.5.0.tgz -C /opt/
ln -s /opt/kafka_2.13-3.5.0 /opt/kafka

# 创建数据目录
mkdir -p /data/kafka/logs
mkdir -p /data/kafka/data

接下来是核心配置——server.properties。这里有几个关键参数,我直接贴出来:

# node-1 的 server.properties
broker.id=101
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://node-1:9092
log.dirs=/data/kafka/data
num.partitions=3
default.replication.factor=2
offsets.topic.replication.factor=2
transaction.state.log.replication.factor=2
transaction.state.log.min.isr=2
zookeeper.connect=zk1:2181/source
zookeeper.connection.timeout.ms=18000
小提示: advertised.listeners 这个参数很容易被忽略。如果客户端和Broker不在同一个网段,必须用这个参数告诉客户端“你应该连哪个地址”。我在跨机房部署时吃过这个亏,客户端一直连不上,查了半天才发现是advertised.listeners没配。

配置完成后,启动ZooKeeper和Kafka:

# 启动ZooKeeper(如果单独部署)
/opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties

# 启动Kafka
/opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties

# 验证
/opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server node-1:9092

其他节点(node-2、node-3)重复上述步骤,只需修改broker.id和advertised.listeners即可。

3.3 搭建目标集群

目标集群的搭建流程几乎一样。区别在于:

  • Broker ID从201开始
  • ZooKeeper路径用/target
  • 监听地址指向目标节点

我直接给一份目标集群的配置差异:

# node-4 的 server.properties(目标集群)
broker.id=201
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://node-4:9092
log.dirs=/data/kafka/data
zookeeper.connect=zk2:2181/target
# 其他参数与源集群保持一致

启动后,用同样的方式验证。我个人习惯在目标集群上创建一个测试Topic,确认生产和消费都正常:

/opt/kafka/bin/kafka-topics.sh --create --topic test-target \
  --bootstrap-server node-4:9092 --partitions 3 --replication-factor 2

/opt/kafka/bin/kafka-console-producer.sh --topic test-target \
  --bootstrap-server node-4:9092

/opt/kafka/bin/kafka-console-consumer.sh --topic test-target \
  --bootstrap-server node-4:9092 --from-beginning

3.4 网络连通性检查

集群搭好了,但MirrorMaker需要从源集群拉数据,再推到目标集群。网络不通的话,后面全是白费功夫。我一般按这个顺序检查:

  1. 基础连通性:用telnet或nc测试端口
  2. DNS解析:确保主机名能正确解析
  3. 防火墙规则:检查iptables或安全组
  4. Kafka协议连通性:用客户端工具验证

具体命令如下:

# 1. 测试端口连通性(在MirrorMaker节点上执行)
telnet node-1 9092
telnet node-4 9092

# 2. 测试DNS解析
nslookup node-1
nslookup node-4

# 3. 检查防火墙(以CentOS为例)
iptables -L -n | grep 9092
# 如果没放行,添加规则
iptables -A INPUT -p tcp --dport 9092 -j ACCEPT

# 4. 用Kafka自带工具验证
/opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server node-1:9092,node-4:9092
注意: 如果两个集群之间有防火墙或安全组,记得放行MirrorMaker节点的出口IP。我曾经遇到过一种情况:源集群和目标集群都在内网,但中间有个NAT网关,MirrorMaker能连上源集群,却连不上目标集群——因为目标集群的安全组没放行NAT网关的IP。排查了整整一个下午。

3.5 JMX监控配置

没有监控的Kafka集群,就像没有仪表盘的飞机。你飞得再高,也不知道什么时候会掉下来。JMX(Java Management Extensions)是Kafka内置的监控接口,我们可以通过它获取Broker的指标数据。

配置JMX很简单,只需要在启动Kafka前设置环境变量:

# 在启动Kafka之前,设置JMX环境变量
export JMX_PORT=9999
export KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.authenticate=false \
  -Dcom.sun.management.jmxremote.ssl=false \
  -Dcom.sun.management.jmxremote.port=9999 \
  -Dcom.sun.management.jmxremote.rmi.port=9999 \
  -Djava.rmi.server.hostname=node-1"

# 然后启动Kafka
/opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties

如果你用的是systemd管理Kafka服务,可以在service文件中添加Environment变量:

[Service]
Environment=JMX_PORT=9999
Environment=KAFKA_JMX_OPTS=-Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.authenticate=false \
  -Dcom.sun.management.jmxremote.ssl=false \
  -Dcom.sun.management.jmxremote.port=9999 \
  -Dcom.sun.management.jmxremote.rmi.port=9999 \
  -Djava.rmi.server.hostname=node-1

配置完成后,用jconsole或jmxterm验证:

# 使用jconsole连接
jconsole node-1:9999

# 或者用jmxterm(命令行工具)
java -jar jmxterm-1.0.4-uber.jar -l node-1:9999
# 进入交互模式后,输入命令查看指标
beans
get -b kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec Count
关键指标清单: 配置好JMX后,建议重点关注以下指标:
  • kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec — 消息流入速率
  • kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec — 字节流入速率
  • kafka.server:type=BrokerTopicMetrics,name=BytesOutPerSec — 字节流出速率
  • kafka.network:type=RequestMetrics,name=TotalTimeMs — 请求处理耗时
  • kafka.log:type=LogFlushStats,name=FlushMs — 刷盘耗时

3.6 整体架构图

下面这张图展示了我们搭建好的整体环境。源集群、目标集群、MirrorMaker节点以及JMX监控的关系一目了然:

MirrorMaker 跨集群复制环境架构 源集群 Broker 101 (node-1) Broker 102 (node-2) Broker 103 (node-3) ZK: zk1:2181/source JMX Port: 9999 目标集群 Broker 201 (node-4) Broker 202 (node-5) Broker 203 (node-6) ZK: zk2:2181/target JMX Port: 9999 MirrorMaker 2.0 节点 消费源集群 → 生产到目标集群 消费数据 生产数据 JMX 监控层 Prometheus + Grafana / JConsole / JMXTerm

3.7 验证与测试

所有配置完成后,我习惯做一次完整的端到端验证。说白了,就是确保源集群能写、目标集群能读、网络通畅、监控能抓到数据。

# 1. 在源集群创建Topic并生产数据
/opt/kafka/bin/kafka-topics.sh --create --topic test-connect \
  --bootstrap-server node-1:9092 --partitions 3 --replication-factor 2

echo "hello mirror" | /opt/kafka/bin/kafka-console-producer.sh \
  --topic test-connect --bootstrap-server node-1:9092

# 2. 在目标集群验证(此时还没有MirrorMaker,所以应该没有数据)
/opt/kafka/bin/kafka-console-consumer.sh --topic test-connect \
  --bootstrap-server node-4:9092 --from-beginning --timeout-ms 5000
# 预期:没有消息

# 3. 验证JMX端口是否开放
telnet node-1 9999
telnet node-4 9999

# 4. 用curl测试JMX指标(如果配置了HTTP适配器)
curl http://node-1:9999/metrics
我的习惯: 在正式部署MirrorMaker之前,我会在源集群和目标集群之间手动跑一次kafka-mirror-maker.sh(旧版)或kafka-mirror-maker2.sh(新版),确认数据能正常复制。虽然这不在本章范围内,但提前验证能帮你排除环境问题。嗯,磨刀不误砍柴工。

好了,环境准备就到这里。源集群、目标集群、网络连通性、JMX监控——四件事都做扎实了,后面配置MirrorMaker的时候,你就能把精力集中在复制策略和性能调优上,而不是被环境问题搞得焦头烂额。