1. 概述

Apache Kafka 是主流的事件流平台,常与 Docker 搭配使用。但实际操作中,客户端(尤其是非同网络或主机的)常遇到连接问题,根源往往在于 Kafka 的 advertised listeners 配置错误。

本教程将深入讲解如何正确配置监听器,确保客户端能稳定连接 Docker 容器中的 Kafka broker。

2. 部署 Kafka

测试连接前,需先通过 Docker 启动 Kafka broker。以下是核心的 docker-compose.yaml 配置片段:

version: '3'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.3.2
    container_name: zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000

  kafka:
    image: confluentinc/cp-kafka:7.3.2
    container_name: kafka
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
      - "29092:29092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL_SAME_HOST:PLAINTEXT
      KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:9092,EXTERNAL_SAME_HOST://localhost:29092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
    networks:
      - kafka_docker_example_net

networks:
  kafka_docker_example_net:
    driver: bridge

关键点说明:

  • 定义了 Kafka 和 Zookeeper 两个核心服务
  • 创建了自定义网络 kafka_docker_example_net
  • 后续会详解 KAFKA_LISTENERSKAFKA_ADVERTISED_LISTENERSKAFKA_LISTENER_SECURITY_PROTOCOL_MAP 配置

启动服务命令:

docker-compose up -d

测试客户端将使用 Kafka 自带的 console producer 工具。若需在宿主机直接运行,需提前下载 Kafka

3. 监听器详解

监听器(Listeners)、公布监听器(Advertised Listeners)和安全协议映射是连接配置的核心。

3.1 监听器基础

通过 KAFKA_LISTENERS 定义 broker 监听的 TCP 套接字列表,格式为逗号分隔的 URI:

KAFKA_LISTENERS: INTERNAL://0.0.0.0:9092,EXTERNAL_SAME_HOST://0.0.0.0:29092

URI 结构解析:

  • 协议名(如 INTERNAL
  • 绑定地址(0.0.0.0 表示所有网络接口)
  • 端口号

踩坑提示:协议名可自定义(如 EXTERNAL_SAME_HOST),但需与后续配置保持一致。

3.2 引导机制(Bootstrapping)

客户端首次连接需通过 bootstrap.servers 指定至少一个 broker 地址。流程如下:

  1. 客户端连接指定 broker
  2. broker 返回集群元数据(含所有 broker 的公布监听器列表)
  3. 后续通信直接使用元数据中的地址

3.3 公布监听器(Advertised Listeners)

KAFKA_ADVERTISED_LISTENERS 告诉客户端如何访问 broker,格式与监听器类似:

KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:9092,EXTERNAL_SAME_HOST://localhost:29092

关键区别:

  • 监听器是 broker 的实际绑定地址
  • 公布监听器是客户端可见的访问地址

3.4 安全协议映射

通过 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP 将自定义协议名映射到安全协议:

KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL_SAME_HOST:PLAINTEXT

示例中 PLAINTEXT 表示:

  • 无需身份认证
  • 数据传输不加密

注意:生产环境应使用 SASL_SSL 等安全协议。

4. 同 Docker 网络内的客户端连接

从另一容器启动 Kafka console producer 测试连接:

docker run --rm --network kafka_docker_example_net \
  confluentinc/cp-kafka:7.3.2 \
  kafka-console-producer --broker-list kafka:9092 --topic test-topic

关键配置:

  • 使用 --network 加入同一网络
  • broker 地址用容器名 kafka:9092
  • 主题自动创建

成功发送消息即表示连接建立。

5. 同宿主机客户端连接

当客户端运行在宿主机(非容器)时,需使用 EXTERNAL_SAME_HOST 监听器。根据公布监听器配置,访问地址为 localhost:29092

使用原生 Kafka 工具测试:

bin/kafka-console-producer.sh --bootstrap-server localhost:29092 --topic test-topic

原理docker-compose.yaml 中的端口映射 29092:29092 使 broker 可被宿主机访问。

6. 跨主机客户端连接

当客户端运行在其他主机时,需新增专用监听器。修改 docker-compose.yaml

environment:
  # 新增跨主机监听器
  KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL_SAME_HOST:PLAINTEXT,EXTERNAL_DIFFERENT_HOST:PLAINTEXT
  KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:9092,EXTERNAL_SAME_HOST://localhost:29092,EXTERNAL_DIFFERENT_HOST://<云主机IP>:29093
ports:
  - "29093:29093"  # 暴露新端口

关键修改:

  1. 新增 EXTERNAL_DIFFERENT_HOST 监听器
  2. 公布地址使用云主机公网 IP(非 localhost
  3. 映射端口 29093 到宿主机

从远程客户端测试:

bin/kafka-console-producer.sh --bootstrap-server <云主机IP>:29093 --topic test-topic

简单粗暴原则:跨主机连接必须用公网 IP + 独立端口组合。

7. 总结

本文系统讲解了 Docker 环境下 Kafka 客户端连接的配置要点:

  • 监听器(Listeners)定义 broker 的绑定地址
  • 公布监听器(Advertised Listeners)声明客户端访问地址
  • 安全协议映射(Security Protocol Map)关联协议与安全机制

核心配置原则:

  1. 同网络用容器名 + 内部端口
  2. 同宿主机用 localhost + 映射端口
  3. 跨主机用公网 IP + 独立映射端口

正确配置这三要素,即可解决 90% 的 Docker-Kafka 连接问题。


原始标题:Connect to Apache Kafka Running in Docker | Baeldung