[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. 不要复用端口,一台机器上的端口不能重复绑定
相关推荐
oMcLin20 小时前
如何在Oracle Linux 8.4上搭建并优化Kafka集群,确保高吞吐量的实时数据流处理与消息传递?
linux·oracle·kafka
码农水水20 小时前
中国邮政Java面试:热点Key的探测和本地缓存方案
java·开发语言·windows·缓存·面试·职场和发展·kafka
掘金-我是哪吒1 天前
Kafka配套的Zookeeper启动脚本
分布式·zookeeper·云原生·kafka
超级种码1 天前
Kafka四部曲之一:Kafka的核心概念
分布式·kafka
u0104058361 天前
基于 Kafka Exactly-Once 语义保障微信群发消息不重复不丢失
分布式·kafka·linq
超级种码1 天前
Kafka四部曲之二:核心架构与设计深度解析
分布式·架构·kafka
新猿一马1 天前
Spring Kafka核心参数说明
kafka
QQ_4376643141 天前
kafka
分布式·kafka
掘金-我是哪吒1 天前
完整的Kafka项目启动流程
分布式·kafka
IT大白2 天前
2、Kafka原理-Producer
分布式·kafka