
集群部署
为了方便测试,本人在同一台机器上基于 docker 容器的形式进行集群的搭建。此外使用 kafka-ui 实现 Kafka 可视化管理,原本是打算使用 Kafka-Eagle 的,但是 Kafka-Eagle 需要依赖 Zookeeper 读取 Kafka 元数据等信息,而我们使用的是 Kafka 4 的版本,官方已经彻底放弃了对 Zookeeper 的支持。因此选择了能兼容 Kafka Kraft 模式 kafka-ui。
为了方便多容器的部署和管理,使用了 docker compose 进行部署。
- 创建 docker-compose.yml
bash
vim docker-compose.yml
docker-compose.yml 文件内容如下:
yaml
version: '3.8'
services:
# --- Kafka 集群配置 ---
kafka1:
image: bitnami/kafka:4.0.0
container_name: kafka1
hostname: kafka1
ports:
- "19092:9092" # 客户端访问端口
- "19093:9093" # Controller内部通信端口
- "19999:9999" # JMX监控端口
environment:
# KRaft核心配置
- KAFKA_CFG_NODE_ID=1
- KAFKA_CFG_PROCESS_ROLES=broker,controller
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
- KAFKA_KRAFT_CLUSTER_ID=test-txing
# 网络与监听器
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.0.128:19092
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
# JMX监控
- KAFKA_JMX_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.0.128
- JMX_PORT=9999
# 生产优化
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=false
- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
- ALLOW_PLAINTEXT_LISTENER=yes
volumes:
- ./broker1/data:/bitnami/kafka
networks:
kafka-net:
ipv4_address: 172.20.0.11
kafka2:
image: bitnami/kafka:4.0.0
container_name: kafka2
hostname: kafka2
ports:
- "29092:9092"
- "29093:9093"
- "29999:9999" # JMX端口需唯一
environment:
- KAFKA_CFG_NODE_ID=2
- KAFKA_CFG_PROCESS_ROLES=broker,controller
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
- KAFKA_KRAFT_CLUSTER_ID=test-txing
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.0.128:29092
# 网络与监听器
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
# JMX监控
- KAFKA_JMX_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.0.128
- JMX_PORT=9999
# 生产优化
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=false
- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
- ALLOW_PLAINTEXT_LISTENER=yes
volumes:
- ./broker2/data:/bitnami/kafka
networks:
kafka-net:
ipv4_address: 172.20.0.12
kafka3:
image: bitnami/kafka:4.0.0
container_name: kafka3
hostname: kafka3
ports:
- "39092:9092"
- "39093:9093"
- "39999:9999" # JMX端口需唯一
environment:
- KAFKA_CFG_NODE_ID=3
- KAFKA_CFG_PROCESS_ROLES=broker,controller
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
- KAFKA_KRAFT_CLUSTER_ID=test-txing
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.0.128:39092
# 网络与监听器
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
# JMX监控
- KAFKA_JMX_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.0.128
- JMX_PORT=9999
# 生产优化
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=false
- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
- ALLOW_PLAINTEXT_LISTENER=yes
volumes:
- ./broker3/data:/bitnami/kafka
networks:
kafka-net:
ipv4_address: 172.20.0.13
# --- 新增 Kafka-UI 监控服务 ---
kafka-ui:
image: provectuslabs/kafka-ui:latest # 官方最新镜像[1,5](@ref)
container_name: kafka-ui
depends_on:
- kafka1
- kafka2
- kafka3
ports:
- "8080:8080" # Web界面端口[1](@ref)
environment:
# 配置连接KRaft集群(直接使用Kafka地址)[6](@ref)
KAFKA_CLUSTERS_0_NAME: "kraft-cluster"
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: "kafka1:9092,kafka2:9092,kafka3:9092"
# JMX监控配置(端口与Kafka服务对应)[2,5](@ref)
KAFKA_CLUSTERS_0_JMXPORT: "19999,29999,39999"
# 可选:添加登录认证[6](@ref)
AUTH_TYPE: "LOGIN_FORM"
SPRING_SECURITY_USER_NAME: "admin"
SPRING_SECURITY_USER_PASSWORD: "admin123"
networks:
kafka-net:
ipv4_address: 172.20.0.15
# --- 网络与存储卷配置 ---
networks:
kafka-net:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
volumes:
broker1-data:
broker2-data:
broker3-data:
- 执行部署
bash
sudo docker-compose up -d
- 查看容器
bash
sudo docker ps
- 查看角色
bash
sudo docker exec kafka1 grep -i 'process.roles' /opt/bitnami/kafka/config/server.properties
输出应包含 broker,controller

- 测试 topic 操作
bash
# 创建 Topic(3分区+3副本)
sudo docker exec kafka1 kafka-topics.sh --create \
--bootstrap-server kafka1:9092 \
--topic test-topic \
--partitions 3 \
--replication-factor 3
# 查看 Topic 分布
sudo docker exec kafka1 kafka-topics.sh --describe \
--bootstrap-server kafka1:9092 \
--topic test-topic
- 生产与消费测试
bash
# 生产者(kafka1 节点)
docker exec -it kafka1 kafka-console-producer.sh \
--bootstrap-server kafka1:9092 \
--topic test-topic
# 消费者(kafka2 节点)
docker exec -it kafka2 kafka-console-consumer.sh \
--bootstrap-server kafka2:9092 \
--topic test-topic \
--from-beginning
注意!!!
为了 Kafka-ui 能监控到 Kafka 的数据,所以每个 broker 都需要打开 JMX 并且暴露对应端口。
但是配置后发现直接使用命令行执行 kafka 的一些操作会报端口占用的相关错误。 这是因为在调用 Kafka 提供的脚本时实际上也是启动了一个短暂的 Java 进程,在启动时会检测是否配置了 JMX,若配置了也会打开 JMX,所以就导致冲突了。
在 github 上有对应的 MR,但是貌似没有被合并,导致现在还是存在这个问题。
github.com/apache/kafk...

- 登陆 Kafka-ui 在 Kafka-ui 可以查看到详细的信息,并且可以方便地完成创建主题等等操作。

项目接入
可参考该仓库进行接入: SpringBoot 项目接入 Kafka demo
- 测试消息发送

- 观察控制台输出

- 在 Kafka-ui 中查看 topic 数据

可以看到,topic 已经被成功创建,消息也已发送并且由消费者成功消费。