[kafka]伪集群搭建,各个节点配置文件中listeners参数的配置

各个节点的 listeners 配置必须不同,因为它们是绑定到不同的端口上的。

一、单机伪集群配置原则

在一台电脑上部署 Kafka 伪集群时:

错误做法(端口冲突):

properties 复制代码
# 节点1
listeners=PLAINTEXT://localhost:9092,CONTROLLER://localhost:9093

# 节点2
listeners=PLAINTEXT://localhost:9092,CONTROLLER://localhost:9093  # ❌ 端口冲突!

正确做法(不同端口):

properties 复制代码
# 节点1
listeners=PLAINTEXT://localhost:9092,CONTROLLER://localhost:9093

# 节点2  
listeners=PLAINTEXT://localhost:9095,CONTROLLER://localhost:9096  # ✅ 不同端口

# 节点3
listeners=PLAINTEXT://localhost:9098,CONTROLLER://localhost:9099  # ✅ 不同端口

二、完整单机伪集群配置示例(3节点)

端口规划表

节点 客户端端口 控制器端口 日志目录
Node1 9092 9093 /tmp/kafka-logs-1
Node2 9095 9096 /tmp/kafka-logs-2
Node3 9098 9099 /tmp/kafka-logs-3

配置文件:

config/kafka1.properties
properties 复制代码
# 基本配置
process.roles=broker,controller
node.id=1

# 监听器配置 - 端口 9092/9093
listeners=PLAINTEXT://localhost:9092,CONTROLLER://localhost:9093
advertised.listeners=PLAINTEXT://localhost:9092

# 数据目录
log.dirs=/tmp/kafka-logs-1

# KRaft 配置
controller.listener.names=CONTROLLER
controller.quorum.voters=1@localhost:9093,2@localhost:9096,3@localhost:9099

# 其他配置
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
num.partitions=1
num.recovery.threads.per.data.dir=1
config/kafka2.properties
properties 复制代码
process.roles=broker,controller
node.id=2

# 监听器配置 - 端口 9095/9096(与节点1不同!)
listeners=PLAINTEXT://localhost:9095,CONTROLLER://localhost:9096
advertised.listeners=PLAINTEXT://localhost:9095

log.dirs=/tmp/kafka-logs-2

controller.listener.names=CONTROLLER
controller.quorum.voters=1@localhost:9093,2@localhost:9096,3@localhost:9099
config/kafka3.properties
properties 复制代码
process.roles=broker,controller
node.id=3

# 监听器配置 - 端口 9098/9099(与其他节点不同!)
listeners=PLAINTEXT://localhost:9098,CONTROLLER://localhost:9099
advertised.listeners=PLAINTEXT://localhost:9098

log.dirs=/tmp/kafka-logs-3

controller.listener.names=CONTROLLER
controller.quorum.voters=1@localhost:9093,2@localhost:9096,3@localhost:9099

三、必须相同的配置 vs 必须不同的配置

必须相同的配置(集群一致性):

properties 复制代码
# 所有节点的这些配置必须完全一致
controller.quorum.voters=1@localhost:9093,2@localhost:9096,3@localhost:9099
controller.listener.names=CONTROLLER
inter.broker.listener.name=PLAINTEXT

必须不同的配置(资源隔离):

properties 复制代码
# 每个节点必须不同
node.id=1                    # 唯一节点ID
listeners=...                # 不同端口
log.dirs=/tmp/kafka-logs-1   # 不同数据目录

四、启动脚本示例

start-kafka-cluster.sh

bash 复制代码
#!/bin/bash

# 生成集群ID(首次运行时使用)
CLUSTER_ID=$(./bin/kafka-storage.sh random-uuid)

echo "集群ID: $CLUSTER_ID"

# 格式化存储目录(首次运行需要)
echo "格式化存储目录..."
./bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kafka1.properties
./bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kafka2.properties  
./bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kafka3.properties

# 启动集群(在三个不同的终端中)
echo "启动节点1..."
./bin/kafka-server-start.sh config/kafka1.properties &

echo "等待5秒..."
sleep 5

echo "启动节点2..."
./bin/kafka-server-start.sh config/kafka2.properties &

echo "等待5秒..."  
sleep 5

echo "启动节点3..."
./bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kafka3.properties

echo "集群启动完成!"

五、验证集群状态

检查端口占用

bash 复制代码
# 查看所有Kafka相关端口
netstat -an | grep -E "9092|9093|9095|9096|9098|9099"

# 或使用 lsof
lsof -i :9092,9093,9095,9096,9098,9099

测试集群功能

bash 复制代码
# 使用任意一个节点的客户端端口
BOOTSTRAP_SERVER="localhost:9092"

# 创建主题
./bin/kafka-topics.sh --bootstrap-server $BOOTSTRAP_SERVER \
  --create --topic test-topic \
  --partitions 3 --replication-factor 3

# 查看主题详情
./bin/kafka-topics.sh --bootstrap-server $BOOTSTRAP_SERVER \
  --describe --topic test-topic

# 查看集群元数据
./bin/kafka-metadata-quorum.sh --bootstrap-server $BOOTSTRAP_SERVER \
  describe --status

六、使用 Docker Compose 的单机伪集群配置

如果你更喜欢用 Docker,这里是一个 docker-compose.yml

yaml 复制代码
version: '3'
services:
  kafka1:
    image: apache/kafka:4.0.1
    container_name: kafka1
    ports:
      - "9092:9092"
      - "9093:9093"
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: "broker,controller"
      KAFKA_LISTENERS: "PLAINTEXT://:9092,CONTROLLER://:9093"
      KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://localhost:9092"
      KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
      KAFKA_CONTROLLER_QUORUM_VOTERS: "1@kafka1:9093,2@kafka2:9093,3@kafka3:9093"
      KAFKA_LOG_DIRS: "/tmp/kafka-logs-1"
    volumes:
      - ./kafka-data-1:/tmp/kafka-logs-1

  kafka2:
    image: apache/kafka:4.0.1
    container_name: kafka2
    ports:
      - "9095:9092"
      - "9096:9093"
    environment:
      KAFKA_NODE_ID: 2
      KAFKA_PROCESS_ROLES: "broker,controller"
      KAFKA_LISTENERS: "PLAINTEXT://:9092,CONTROLLER://:9093"
      KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://localhost:9095"
      KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
      KAFKA_CONTROLLER_QUORUM_VOTERS: "1@kafka1:9093,2@kafka2:9093,3@kafka3:9093"
      KAFKA_LOG_DIRS: "/tmp/kafka-logs-2"
    volumes:
      - ./kafka-data-2:/tmp/kafka-logs-2

  kafka3:
    image: apache/kafka:4.0.1
    container_name: kafka3
    ports:
      - "9098:9092"
      - "9099:9093"
    environment:
      KAFKA_NODE_ID: 3
      KAFKA_PROCESS_ROLES: "broker,controller"
      KAFKA_LISTENERS: "PLAINTEXT://:9092,CONTROLLER://:9093"
      KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://localhost:9098"
      KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
      KAFKA_CONTROLLER_QUORUM_VOTERS: "1@kafka1:9093,2@kafka2:9093,3@kafka3:9093"
      KAFKA_LOG_DIRS: "/tmp/kafka-logs-3"
    volumes:
      - ./kafka-data-3:/tmp/kafka-logs-3

七、常见问题解决

问题1:端口已占用

bash 复制代码
# 解决方案:修改端口
# 节点1:9092,9093 → 修改为 19092,19093
# 节点2:9095,9096 → 修改为 19095,19096
# 节点3:9098,9099 → 修改为 19098,19099

问题2:启动顺序问题

bash 复制代码
# KRaft 模式需要至少一个控制器先启动
# 解决方案:逐个启动,间隔几秒
./bin/kafka-server-start.sh config/kafka1.properties
# 等待10秒
./bin/kafka-server-start.sh config/kafka2.properties
# 等待10秒
./bin/kafka-server-start.sh config/kafka3.properties

问题3:数据目录冲突

bash 复制代码
# 解决方案:使用不同的目录
log.dirs=/tmp/kafka-cluster/node1
log.dirs=/tmp/kafka-cluster/node2
log.dirs=/tmp/kafka-cluster/node3

八、简化的配置方法(使用脚本自动生成)

generate-configs.sh

bash 复制代码
#!/bin/bash

BASE_PORT=9092
CONTROLLER_BASE_PORT=9093
NODES=3

for i in $(seq 1 $NODES); do
  CLIENT_PORT=$((BASE_PORT + (i-1)*3))
  CONTROLLER_PORT=$((CONTROLLER_BASE_PORT + (i-1)*3))
  
  cat > config/kafka$i.properties << EOF
# 自动生成的配置 - 节点$i
process.roles=broker,controller
node.id=$i

listeners=PLAINTEXT://localhost:$CLIENT_PORT,CONTROLLER://localhost:$CONTROLLER_PORT
advertised.listeners=PLAINTEXT://localhost:$CLIENT_PORT

log.dirs=/tmp/kafka-logs-$i

controller.listener.names=CONTROLLER
controller.quorum.voters=1@localhost:9093,2@localhost:9096,3@localhost:9099

num.partitions=3
default.replication.factor=3
min.insync.replicas=2
EOF
  
  echo "生成 config/kafka$i.properties: client_port=$CLIENT_PORT, controller_port=$CONTROLLER_PORT"
done

总结关键点

  1. 每个节点必须有唯一的端口组合
  2. controller.quorum.voters 必须完全相同
  3. 数据目录必须不同
  4. 节点ID必须唯一
  5. 不要复用端口,一台机器上的端口不能重复绑定
相关推荐
富士康质检员张全蛋2 天前
Kafka 事物
kafka
wear工程师3 天前
Kafka 消费者心跳正常,为什么还会被踢出组?拆清 max.poll.interval.ms
java·kafka
成为你的宁宁4 天前
【Kafka KRaft 集群】
分布式·kafka
2601_960906725 天前
地球或逃逸到相对安全的日心轨道
kafka·hbase·flume·storm
creator_Li5 天前
Kafka深入刨析-Consumer
分布式·kafka
JHC0000006 天前
基于 DrissionPage 与 Xvfb 的分布式无头爬虫架构
分布式·kafka
java1234_小锋7 天前
【免费】基于Spark实时医疗健康数据监测与疾病预测系统(Java版本+可视化大屏+Kafka+SpringBoot+Vue3) 锋哥原创出品,必属精品
大数据·spark·kafka·实时医疗健康数据监测·实时疾病预测系统
菜地里的小菜鸟8 天前
k8s部署单节点 Kafka(KRaft 模式)并启用 SASL 认证
kafka·kraft·k8s部署单节点kafkakraft模式·k8s部署kafka
Volunteer Technology8 天前
Kafka的消费全流程
分布式·kafka·linq
篮框坏了8 天前
Kafka 消费者卡死排查:一个 topic 堵了 18 小时,监控全绿没人发现
kafka