[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. 不要复用端口,一台机器上的端口不能重复绑定
相关推荐
Mr.朱鹏18 小时前
SQL深度分页问题案例实战
java·数据库·spring boot·sql·spring·spring cloud·kafka
山沐与山1 天前
【MQ】Kafka与RocketMQ深度对比
分布式·kafka·rocketmq
yumgpkpm1 天前
Cloudera CDP7、CDH5、CDH6 在华为鲲鹏 ARM 麒麟KylinOS做到无缝切换平缓迁移过程
大数据·arm开发·华为·flink·spark·kafka·cloudera
树下水月1 天前
Easyoole 使用rdkafka 进行kafka的创建topic创建 删除 以及数据发布 订阅
分布式·kafka
Cat God 0071 天前
基于Docker搭建kafka集群
docker·容器·kafka
Cat God 0071 天前
基于 Docker 部署 Kafka(KRaft + SASL/PLAIN 认证)
docker·容器·kafka
KD1 天前
设计模式——责任链模式实战,优雅处理Kafka消息
后端·设计模式·kafka
原神启动12 天前
Kafka详解
分布式·kafka