现象:
controller节点与其他两个broker的通信失败。公网ip,宿主机ip,服务名,各种网络方式,都无法成功。
两点提示:
1.bug原因:因为单机内存不够用,设置了较低的 KAFKA_HEAP_OPTS 参数值128M,导致broker通信失败!
2.kafka容器启动中,增加 BITNAMI_DEBUG=true 参数,可通过 docker logs 命令查看更为细节的日志信息!
以下为 执行 docker-compose up -d 时,会成功的 docker-compose.yml文件内容:
version: "2.12"
services:
kafkas1:
image: 'bitnami/kafka:3.2.3'
container_name: kafkas1
user: root
ports:
- '9092:9092'
- '9093:9093'
environment:
- KAFKA_ENABLE_KRAFT=yes
- KAFKA_CFG_PROCESS_ROLES=broker,controller
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafkas1:9092
- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT
- KAFKA_NODE_ID=1
- KAFKA_CFG_BROKER_ID=1
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafkas1:9093,2@kafkas2:9095,3@kafkas3:9097
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_HEAP_OPTS=-Xmx256m -Xms256m
- KAFKA_KRAFT_CLUSTER_ID=7es-47FeQpCKpLfsN1uPxQ
- BITNAMI_DEBUG=true
volumes:
- /usr/local/kafka/kafka1/data:/bitnami/kafka
networks:
- kafka_standalone_net
kafkas2:
image: 'bitnami/kafka:3.2.3'
container_name: kafkas2
user: root
ports:
- '9094:9094'
- '9095:9095'
environment:
- KAFKA_ENABLE_KRAFT=yes
- KAFKA_CFG_PROCESS_ROLES=broker,controller
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9094,CONTROLLER://:9095
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafkas2:9094
- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT
- KAFKA_NODE_ID=2
- KAFKA_CFG_BROKER_ID=2
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafkas1:9093,2@kafkas2:9095,3@kafkas3:9097
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_HEAP_OPTS=-Xmx256m -Xms256m
- KAFKA_KRAFT_CLUSTER_ID=7es-47FeQpCKpLfsN1uPxQ
- BITNAMI_DEBUG=true
volumes:
- /usr/local/kafka/kafka2/data:/bitnami/kafka
networks:
- kafka_standalone_net
kafkas3:
image: 'bitnami/kafka:3.2.3'
container_name: kafkas3
user: root
ports:
- '9096:9096'
- '9097:9097'
environment:
- KAFKA_ENABLE_KRAFT=yes
- KAFKA_CFG_PROCESS_ROLES=broker,controller
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9096,CONTROLLER://:9097
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafkas3:9096
- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT
- KAFKA_NODE_ID=3
- KAFKA_CFG_BROKER_ID=3
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafkas1:9093,2@kafkas2:9095,3@kafkas3:9097
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_HEAP_OPTS=-Xmx256m -Xms256m
- KAFKA_KRAFT_CLUSTER_ID=7es-47FeQpCKpLfsN1uPxQ
- BITNAMI_DEBUG=true
volumes:
- /usr/local/kafka/kafka3/data:/bitnami/kafka
networks:
- kafka_standalone_net
networks:
kafka_standalone_net:
driver: bridge
topic,producer,consumer,测试相关命令:
# 随便进入一个容器节点
docker exec -it kafkas1 /bin/bash
# 创建topic,1个partition,1个replication
/opt/bitnami/kafka/bin/kafka-topics.sh --bootstrap-server kafkas1:9092 --create --topic firsttopic --partitions 1 --replication-factor 1
# 查看已存在topic列表
/opt/bitnami/kafka/bin/kafka-topics.sh --bootstrap-server kafkas1:9092 --list
# 创建producer
/opt/bitnami/kafka/bin/kafka-console-producer.sh --bootstrap-server kafkas1:9092 --topic firsttopic
# 再起一个窗口,随便连接一个容器节点,创建consumer
docker exec -it kafkas1 /bin/bash
/opt/bitnami/kafka/bin/kafka-console-consumer.sh --bootstrap-server kafkas1:9092 --topic firsttopic
### 上面所有的 kafkas1,都可以随便替换为 kafkas2,kafkas3,任意节点都一样。
### 当然,端口要对应上
如上内容,其他都不变,只把 KAFKA_HEAP_OPTS 参数值的 256m 改为 128m,就会失败。
我是因为测试服务器内存实在太小,才会特意设置这个参数,算是遇到了奇葩坑。
官网没看到相关描述,整个文档搜索 heap ,就没有相关的,应该是没说明。
个人猜测,是因为内存不足,导致controller和broker通信时,网络IO链条上的某个部位内存分配函数调用失败,无法工作了。
另外,我的测试服务器是2G内存,基本算是只有docker和kafka了,设置完256m以后,创建一个topic时,partition、replication都设置了1,要不然,后面再创建producer时,又内存不足失败了。
其他常见关注点:
- KAFKA_ENABLE_KRAFT=yes参数,代表kraft模式,也就是弃用zookeeper
- 一个节点,可以为broker,可以为controller,也可以同时broker和controller
- listeners是描述本节点监听哪里(包括监听客户端的,和其他broker和controller的),advertised.listeners是告诉controller节点客户端访问我哪里
- controller.listener.names是说明controller相关通信用哪个名字的协议,inter.broker.listener.name是说明broker相关通信用哪个名字的协议。都在内网就用plaintext,都在公网就可以用ssl之类的,用来规划各个点之间通信安全的。
- KAFKA_KRAFT_CLUSTER_ID=7es-47FeQpCKpLfsN1uPxQ 是节点之间作为同一集群的标记,具体内容无所谓,你也可以用我的。
顺便想问一下:
为什么上面的docker-compose.yml中,9093,9095,9097,端口不暴露出去,也可以启动成功,正常使用???以我的理解,不应该呀!懂的教教我