Docker环境下Spring Boot Kafka生产者报错排查与配置优化咨询
问题描述
我正在尝试创建一个Spring Boot生产者应用并在Docker中运行,已经编写了包含PostgreSQL数据库与Kafka镜像的Docker Compose配置文件。启动容器后,Broker和生产者应用分别出现错误,附上我的docker-compose.yml和Dockerfile,希望得到问题排查方案和配置优化建议(刚接触Docker)。
Broker错误日志
[2024-02-10 07:41:13,201] INFO [Controller id=1] Skipping preferred replica election for partitions due to topic deletion: (kafka.controller.KafkaController) 2024-02-10T07:41:13.202837919Z [2024-02-10 07:41:13,201] WARN [RequestSendThread controllerId=1] Controller 1's connection to broker broker:9092 (id: 1 rack: null) was unsuccessful (kafka.controller.RequestSendThread) 2024-02-10T07:41:13.202843669Z java.io.IOException: Connection to broker:9092 (id: 1 rack: null) failed. 2024-02-10T07:41:13.202845419Z at org.apache.kafka.clients.NetworkClientUtils.awaitReady(NetworkClientUtils.java:70) 2024-02-10T07:41:13.202854544Z at kafka.controller.RequestSendThread.brokerReady(ControllerChannelManager.scala:298) 2024-02-10T07:41:13.202856336Z at kafka.controller.RequestSendThread.doWork(ControllerChannelManager.scala:251) 2024-02-10T07:41:13.202857794Z at org.apache.kafka.server.util.ShutdownableThread.run(ShutdownableThread.java:127)
生产者应用错误日志
2024-02-10T07:41:51.769527256Z 2024-02-10T07:41:51.768Z INFO 1 --- [| adminclient-1] org.apache.kafka.clients.NetworkClient : [AdminClient clientId=adminclient-1] Node -1 disconnected. 2024-02-10T07:41:51.769663798Z 2024-02-10T07:41:51.769Z WARN 1 --- [| adminclient-1] org.apache.kafka.clients.NetworkClient : [AdminClient clientId=adminclient-1] Connection to node -1 (localhost/127.0.0.1:9092) could not be established. Broker may not be available. 2024-02-10T07:41:52.803914007Z
现有配置文件
docker-compose.yml
version: "2" services: producer: image: "spring-boot-kafka-producer:latest" build: context: . container_name: producer depends_on: - database - broker - zookeeper env_file: .env ports: - "8080:8080" environment: - SPRING_DATASOURCE_URL=${SPRING_DATASOURCE_URL} - SPRING_DATASOURCE_USERNAME=${POSTGRESDB_USER} - SPRING_DATASOURCE_PASSWORD=${POSTGRESDB_ROOT_PASSWORD} - SPRING_JPA_HIBERNATE_DDL_AUTO=update - spring.kafka.producer.bootstrap-servers=broker:9092 - spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer - spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer volumes: - .m2:/root/.m2 tty: true stdin_open: true database: image: 'postgres:13.1-alpine' container_name: database restart: unless-stopped env_file: - .env environment: - POSTGRES_USER=${POSTGRESDB_USER} - POSTGRES_PASSWORD=${POSTGRESDB_ROOT_PASSWORD} - POSTGRES_DB=${POSTGRESDB_DATABASE} ports: - "5432:5432" zookeeper: image: confluentinc/cp-zookeeper:latest environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 ZOOKEEPER_HOST: zookeeper ports: "2181:2181" broker: image: confluentinc/cp-enterprise-kafka:latest hostname: broker container_name: broker depends_on: - zookeeper ports: - "29092:29092" - "29093:29093" - "9092:9092" environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: INTERNAL://broker:9092,EXTERNAL_SAME_HOST://localhost:29092,EXTERNAL_DIFFERENT_HOST://157.245.80.232:29093 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL_SAME_HOST:PLAINTEXT,EXTERNAL_DIFFERENT_HOST:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_LISTENERS: INTERNAL://:9092,EXTERNAL_SAME_HOST://:29092,EXTERNAL_DIFFERENT_HOST://:29093 restart: unless-stopped
Dockerfile
FROM azul/zulu-openjdk-alpine:17-jre-latest LABEL description="Spring boot producer application to explore the various funtionalities spring offers for kakfa" ARG JAR_FILE=*.jar COPY ${JAR_FILE} application.jar ENTRYPOINT ["java", "-jar", "application.jar"] HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
问题排查与优化建议
1. 错误原因分析
Broker连接失败
核心问题是Zookeeper配置的语法错误:ports配置被错误嵌套在environment块内,导致Zookeeper无法正常启动,进而Kafka Broker无法连接Zookeeper,触发控制器连接失败的错误。
生产者连接错误
虽然docker-compose中配置了spring.kafka.producer.bootstrap-servers=broker:9092,但日志显示生产者尝试连接localhost:9092,大概率是以下两种情况:
- Spring Boot应用的配置文件(如application.yml/properties)中硬编码了
bootstrap-servers=localhost:9092,覆盖了环境变量配置 - 环境变量未正确注入到容器中,可进入容器执行
printenv | grep kafka验证
2. 配置修复方案
修复Zookeeper配置
将ports移出environment块,修正后的Zookeeper配置如下:
zookeeper: image: confluentinc/cp-zookeeper:latest environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 ZOOKEEPER_HOST: zookeeper ports: - "2181:2181"
确认生产者Kafka配置
- 检查应用配置文件,删除硬编码的
bootstrap-servers配置 - 进入生产者容器执行
printenv | grep kafka,确认spring.kafka.producer.bootstrap-servers=broker:9092已正确注入
优化容器启动顺序(可选)
depends_on仅保证容器启动顺序,不保证服务就绪。添加健康检查确保依赖服务就绪后再启动生产者:
- 给Zookeeper添加健康检查:
zookeeper: # ... 其他配置 healthcheck: test: ["CMD", "zkServer.sh", "status"] interval: 10s timeout: 5s retries: 5
- 给Broker添加健康检查:
broker: # ... 其他配置 healthcheck: test: ["CMD", "kafka-topics.sh", "--list", "--bootstrap-server", "localhost:9092"] interval: 10s timeout: 5s retries: 5
- 修改生产者的
depends_on:
producer: # ... 其他配置 depends_on: database: condition: service_healthy broker: condition: service_healthy zookeeper: condition: service_healthy
3. Docker配置优化建议
版本与镜像选择
- 将docker-compose版本升级到
3.8或更高,支持更多特性(如健康检查依赖) - 替换Kafka企业版镜像为社区版
confluentinc/cp-kafka:latest,减少资源占用 - 升级PostgreSQL镜像到最新稳定版(如
postgres:16-alpine),提升性能与安全性
添加资源限制
为每个容器设置资源上限,避免单个容器耗尽主机资源:
services: producer: # ... 其他配置 deploy: resources: limits: cpus: '1' memory: 1G reservations: cpus: '0.5' memory: 512M database: # ... 其他配置 deploy: resources: limits: cpus: '1' memory: 1G reservations: cpus: '0.5' memory: 512M zookeeper: # ... 其他配置 deploy: resources: limits: cpus: '0.5' memory: 512M reservations: cpus: '0.25' memory: 256M broker: # ... 其他配置 deploy: resources: limits: cpus: '1' memory: 2G reservations: cpus: '0.5' memory: 1G
数据持久化
添加数据卷避免容器销毁后数据丢失:
- 为PostgreSQL和Kafka添加数据卷:
database: # ... 其他配置 volumes: - postgres-data:/var/lib/postgresql/data broker: # ... 其他配置 volumes: - kafka-data:/var/lib/kafka/data
- 在docker-compose.yml末尾定义卷:
volumes: postgres-data: kafka-data:
生产者容器优化
- 移除
tty: true和stdin_open: true,生产环境不需要交互模式 - 修改健康检查端点:如果应用没有根路径接口,改为Spring Boot Actuator的健康检查端点(需添加Actuator依赖),示例:
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost:8080/actuator/health || exit 1
内容的提问来源于stack exchange,提问作者Aravindraj Ganesan
相关产品推荐
相关产品推荐

