Docker部署Kafka多Broker结合Log4j发消息故障转移配置问题
回答
首先直接回应你的认知问题:这个认知不完全正确,缺了两个必要前提:
- 客户端配置的
bootstrap.servers初始连接列表里,至少要有一个节点是存活可访问的,否则客户端连集群都连不上,根本没机会拉取全集群元数据 - 客户端从集群拉取到的所有Broker的advertised地址,必须是客户端自身网络环境下可访问的,否则就算拿到元数据也连不上其他节点
你现在的故障转移失效,是Broker配置、客户端配置都存在硬伤导致的,具体问题和修复方式如下:
现有配置的核心错误
- Broker监听配置缺失:你只配置了
KAFKA_ADVERTISED_LISTENERS,没有配置KAFKA_LISTENERS告诉Broker需要在哪些端口绑定监听。Confluent的Kafka镜像默认只会监听9092端口,你配置的19092、19093对外映射端口,还有Broker2写的9093内部通信端口,实际上都没有进程监听,不仅外部客户端连19093端口会失败,两个Broker之间的副本同步也会出问题。 - Broker内部通信端口配置混乱:你给Broker2的PLAINTEXT listener配置了9093端口,但因为没配listeners参数,Broker2实际还是监听9092,集群内部通信本身就不正常。容器网络下每个Broker是独立网络栈,完全不需要用不同端口区分,两个Broker都用9092作为内部通信端口即可。
- 所有客户端的初始连接列表只配了单个Broker:不管是Log4j Appender还是kafka-ui,bootstrap.servers都只填了Broker1的地址,Broker1被kill后,客户端初始连接直接失败,根本没有机会获取集群其他节点的元数据。
- kafka-ui的ZooKeeper地址配置错误:你写的是
localhost:2181,但kafka-ui运行在独立容器里,它的localhost上没有运行ZooKeeper服务,之前能正常访问全靠连Broker1拉数据,Broker1挂了之后连ZooKeeper也连不上,自然看不到任何Topic。 - 缺少Broker间通信监听器配置:没有指定
KAFKA_INTER_BROKER_LISTENER_NAME,Broker间通信的监听器不明确,副本同步逻辑不稳定。
修复步骤
1. 修正docker-compose.yml配置
首先修正两个Broker的环境变量配置,补全监听规则:
# brdg-broker-one 环境变量部分 environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: brdg-zookeeper:2181 # 明确指定Broker需要绑定监听的地址,0.0.0.0表示监听所有网卡 KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONNECTIONS_FROM_HOST://0.0.0.0:19092 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://brdg-broker-one:9092,CONNECTIONS_FROM_HOST://localhost:19092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONNECTIONS_FROM_HOST:PLAINTEXT # 指定Broker间通信用PLAINTEXT监听器 KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 2 # 单节点存活时即可提供服务,避免一个节点挂了集群直接不可用 KAFKA_MIN_INSYNC_REPLICAS: 1
# brdg-broker-two 环境变量部分 environment: KAFKA_BROKER_ID: 2 KAFKA_ZOOKEEPER_CONNECT: brdg-zookeeper:2181 KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONNECTIONS_FROM_HOST://0.0.0.0:19093 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://brdg-broker-two:9092,CONNECTIONS_FROM_HOST://localhost:19093 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONNECTIONS_FROM_HOST:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 2 KAFKA_MIN_INSYNC_REPLICAS: 1
然后修正kafka-ui的环境变量配置:
environment: - KAFKA_CLUSTERS_0_NAME=local # 初始连接列表填两个Broker的内部地址,一个挂了还能连另一个 - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=brdg-broker-one:9092,brdg-broker-two:9092 # ZooKeeper地址填容器网络内的服务名,不要写localhost - KAFKA_CLUSTERS_0_ZOOKEEPER=brdg-zookeeper:2181
2. 修正Log4j2的Kafka Appender配置
把bootstrap.servers配置改成两个节点的对外地址:
<Property name="bootstrap.servers">localhost:19092,localhost:19093</Property>
3. 重建集群并验证
- 先删除旧的容器和卷(旧集群的元数据因为之前配置错误已经不可用,直接重建最省事),执行
docker-compose down -v后再docker-compose up -d启动 - 新建Topic时一定要指定
--replication-factor 2,确保每个Topic的副本分布在两个Broker上,包括你要用的logInfo主题。之前如果已经创建过副本数为1的Topic,需要手动执行副本重分配把副本扩到2个,否则对应Broker挂了这个Topic就不可用。 - 故障转移不是秒级生效,Broker被kill后需要等5-15秒让集群完成控制器选举、副本leader切换,之后客户端就能自动恢复发送。
内容的提问来源于stack exchange,提问作者Rafe
相关产品推荐
相关产品推荐

