美文网首页
wsl 中 docker-compose 搭建 kafka 集群

wsl 中 docker-compose 搭建 kafka 集群

作者: Assassin007 | 来源:发表于2023-03-25 17:07 被阅读0次

    在 wsl 中用 docker-compose 搭建了一台 zookeeper + 三台 broker 的 kafka 集群,使用的镜像是 bitnami/kafka,在按照镜像文档运行容器后,发现运行在宿主机里的客户端程序无法正确的推送/消费消息,研究后发现镜像文档只适用于客户端程序和 kafka 集群同属于一个 docker 网段,外部访问还需要一些额外的配置,过程中出现过以下几个主要的错误:

    • dial tcp: lookup 333be5d4e335 on 172.30.96.1:53: no such host
    • kafka: client has run out of available brokers to talk to: dial tcp 127.0.0.1:19092: connect: connection refused
    • [Controller id=1, targetBrokerId=3] Client requested connection close from node 3 (org.apache.kafka.clients.NetworkClient)

    这里先贴一个可以用的 docker-compose.yml 配置,后面对其中的关键配置做一个解释,最后再解释出现上面错误的原因,文件最后的 kafka-ui 是一个可视化管理界面,可以不要

    version: "3"
    
    services:
      zookeeper:
        container_name: kafka_zookeeper
        image: bitnami/zookeeper
        user: root
        ports:
          - "2181:2181"
        environment:
          - ALLOW_ANONYMOUS_LOGIN=yes
        volumes:
          - ./zookeeper:/bitnami/zookeeper
      broker1:
        container_name: kafka_broker1
        image: bitnami/kafka
        user: root
        ports:
          - "19092:9092"
        environment:
          - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
          - ALLOW_PLAINTEXT_LISTENER=yes
          - KAFKA_BROKER_ID=1
          - KAFKA_LISTENERS=INTERNAL://0.0.0.0:9000,EXTERNAL://0.0.0.0:9092
          - KAFKA_ADVERTISED_LISTENERS=INTERNAL://broker1:9000,EXTERNAL://localhost:19092
          - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
          - KAFKA_INTER_BROKER_LISTENER_NAME=INTERNAL
        volumes:
          - ./broker1:/bitnami/kafka
        depends_on:
          - zookeeper
      broker2:
        container_name: kafka_broker2
        image: bitnami/kafka
        user: root
        ports:
          - "29092:9092"
        environment:
          - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
          - ALLOW_PLAINTEXT_LISTENER=yes
          - KAFKA_BROKER_ID=2
          - KAFKA_LISTENERS=INTERNAL://0.0.0.0:9000,EXTERNAL://0.0.0.0:9092
          - KAFKA_ADVERTISED_LISTENERS=INTERNAL://broker2:9000,EXTERNAL://localhost:29092
          - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
          - KAFKA_INTER_BROKER_LISTENER_NAME=INTERNAL
        volumes:
          - ./broker2:/bitnami/kafka
        depends_on:
          - broker1
      broker3:
        container_name: kafka_broker3
        image: bitnami/kafka
        user: root
        ports:
          - "39092:9092"
        environment:
          - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
          - ALLOW_PLAINTEXT_LISTENER=yes
          - KAFKA_BROKER_ID=3
          - KAFKA_LISTENERS=INTERNAL://0.0.0.0:9000,EXTERNAL://0.0.0.0:9092
          - KAFKA_ADVERTISED_LISTENERS=INTERNAL://broker3:9000,EXTERNAL://localhost:39092
          - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
          - KAFKA_INTER_BROKER_LISTENER_NAME=INTERNAL
        volumes:
          - ./broker3:/bitnami/kafka
        depends_on:
          - broker2
      kafka-ui:
        container_name: kafka-ui
        image: provectuslabs/kafka-ui
        ports:
          - "8080:8080"
        restart: always
        environment:
          - KAFKA_CLUSTERS_0_NAME=broker1
          - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=broker1:9000
          - KAFKA_CLUSTERS_1_NAME=broker2
          - KAFKA_CLUSTERS_1_BOOTSTRAPSERVERS=broker2:9000
          - KAFKA_CLUSTERS_2_NAME=broker3
          - KAFKA_CLUSTERS_2_BOOTSTRAPSERVERS=broker3:9000
        depends_on:
          - broker3
    

    其中几个容易搞错的关键配置如下:

    ports:
      - "19092:9092"
    environment:
      - KAFKA_LISTENERS=INTERNAL://0.0.0.0:9000,EXTERNAL://0.0.0.0:9092
      - KAFKA_ADVERTISED_LISTENERS=INTERNAL://broker1:9000,EXTERNAL://localhost:19092
    

    参数 KAFKA_LISTENERS 和 KAFKA_ADVERTISED_LISTENERS 的作用:

    • KAFKA_LISTENERS 代表 broker 的监听地址,kafka客户端首先需要与这个地址建立连接,完成必要的认证工作
    • KAFKA_ADVERTISED_LISTENERS 代表 broker 的数据传输地址,这里配置的地址会注册到 zookeeper 中,在客户端完成身份认证后会从 zk 原封不动地获得这里配置的 ip+port 用于消息推送/消费

    在上面的配置中,KAFKA_ADVERTISED_LISTENERS 的 EXTERNAL 配置了 localhost:19092,这是因为我的客户端程序运行在 wsl 中,而 19092 端口已经映射到了容器的 9092 端口上所以可以正确访问,如果 kafka 集群和客户端程序运行在两个不同的服务器上,这里应该配置 kfaka 集群所在的主机 ip,只需要记住这一串地址的 ip+port 部分是原封不动的传给客户端的,想想客户端程序所在的机器能不能解析它吧

    另外,关于 KAFKA_LISTENERS 中 port 的配置与上面 ports 属性中的端口映射的关系是:先有端口监听后有端口映射,这个地方没理解清楚的话就很容易对这两个配置项感到迷惑,例如上面配置了 9000 和 9092 两个监听端口,然后将 9092 映射到了宿主机的 19092,9000 作为未公开的端口只有同属一个 docker 网络的机器才能访问

    一开始出现的几个主要错误也都是由这几个配置引起:

    • dial tcp: lookup 333be5d4e335 on 172.30.96.1:53: no such host

    未配置 KAFKA_LISTENERS 的情况下默认是该 broker 容器的主机名+9092,未配置 KAFKA_ADVERTISED_LISTENERS 的情况下该值等于 KAFKA_LISTENERS,这种情况下宿主机的程序建立连接后拿到了一个未知的主机名 333be5d4e335 发送消息,当然行不通(宿主机无法将该主机名转换成 ip 访问)

    • kafka: client has run out of available brokers to talk to: dial tcp 127.0.0.1:19092: connect: connection refused

    端口配置没有理解清楚,KAFKA_LISTENERS 中对外的监听端口必须是被映射出去的 9092 本身,否则宿主机无法访问

    • [Controller id=1, targetBrokerId=3] Client requested connection close from node 3 (org.apache.kafka.clients.NetworkClient)

    端口配置没有理解清楚,brokers 之间的通信是内部通信,内部监听端口可以不公开映射出去,但是流程是一样的

    另外在配置项变更后,最好删除容器,并删除各个目录里面的 data 目录里面的文件再重新创建容器,不确定是哪一个配置变更会出现以下错误:

    • org.apache.zookeeper.KeeperException$NodeExistsException: KeeperErrorCode = NodeExists

    相关文章

      网友评论

          本文标题:wsl 中 docker-compose 搭建 kafka 集群

          本文链接:https://www.haomeiwen.com/subject/sisnrdtx.html