wsl 中 docker-compose 搭建 kafka 集群出现的外部访问错误
在 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 集群出现的外部访问错误的更多相关文章
- 用 Docker 快速搭建 Kafka 集群
开源Linux 一个执着于技术的公众号 版本 •JDK 14•Zookeeper•Kafka 安装 Zookeeper 和 Kafka Kafka 依赖 Zookeeper,所以我们需要在安装 Kaf ...
- Docker实战之Kafka集群
1. 概述 Apache Kafka 是一个快速.可扩展的.高吞吐.可容错的分布式发布订阅消息系统.其具有高吞吐量.内置分区.支持数据副本和容错的特性,适合在大规模消息处理场景中使用. 笔者之前在物联 ...
- docker-compose 搭建kafka集群
docker-compose搭建kafka集群 下载镜像 1.wurstmeister/zookeeper 2.wurstmeister/kafka 3.sheepkiller/kafka-manag ...
- 大数据平台搭建-kafka集群的搭建
本系列文章主要阐述大数据计算平台相关框架的搭建,包括如下内容: 基础环境安装 zookeeper集群的搭建 kafka集群的搭建 hadoop/hbase集群的搭建 spark集群的搭建 flink集 ...
- centos7搭建kafka集群-第二篇
好了,本篇开始部署kafka集群 Zookeeper集群搭建 注:Kafka集群是把状态保存在Zookeeper中的,首先要搭建Zookeeper集群(也可以用kafka自带的ZK,但不推荐) 1.软 ...
- Kafka学习之(六)搭建kafka集群
想要搭建kafka集群,必须具备zookeeper集群,关于zookeeper集群的搭建,在Kafka学习之(五)搭建kafka集群之Zookeeper集群搭建博客有说明.需要具备两台以上装有zook ...
- 什么是kafka以及如何搭建kafka集群?
一.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据. Kafka场景比喻 接下来我大概比喻下Kafka的使用场景 消息中间件:生产者和消费者 妈妈:生产 ...
- 利用新版本自带的Zookeeper搭建kafka集群
安装简要说明新版本的kafka自带有zookeeper,其实自带的zookeeper完全够用,本篇文章以记录使用自带zookeeper搭建kafka集群.1.关于kafka下载kafka下载页面:ht ...
- docker容器中搭建kafka集群环境
Kafka集群管理.状态保存是通过zookeeper实现,所以先要搭建zookeeper集群 zookeeper集群搭建 一.软件环境: zookeeper集群需要超过半数的的node存活才能对外服务 ...
- docker搭建kafka集群(高级版)
1. 环境docker, docker-compose 2.zookeeper集群 /data/zookeeper/zoo1/config/zoo.cfg # The number of millis ...
随机推荐
- jQuery测试用例-W3school
$("div").scrollLeft(100); // 设置滚动条的位置 $(document).ready(function(){ $("button"). ...
- mysql安装及可视化界面
Mysql下载安装 官网下载链接 https://dev.mysql.com/downloads/mysql/ 可以选择之前的版本 我一开始下的8.0.21但安装的时候报错说找不到VCRUNTIME1 ...
- 对synchronized的理解和Spring为什么是单例的
只有真正理解了Java中对象是什么,才能理解这个关键字是什么意思 字面解释 Java Guide中如此解释: synchronized 关键字解决的是多个线程之间访问资源的同步性,synchroniz ...
- Debug --> 箱线图
箱线图主要用于反映原始数据分布的特征,还可以进行多组数据分布特征的比较. 箱形图最大的优点就是不受异常值的影响,能够准确稳定地描绘出数据的离散分布情况,同时也利于数据的清洗. 在箱图中,最上方和最下方 ...
- Jmeter七、jmeter中的参数化
参数化是为了更好的模拟真实的业务场景 CSV data set config组件 1.更容易使用和理解 2.适合大参数量场景 3.设置方便灵活 EOF=end of file 没有找到文件 comma ...
- 微信小程序主包和分包的资源可以相互引用吗
了解主包.分包 整个小程序所有分包大小不超过20M;单个分包/主包大小不能超过 2M 主包: a. 放置默认启动页面&&tabBar页面, 以及一些分包需要用到的公共资源(如wxss. ...
- vue 组件之间事件触发($emit)与event Bus($on)的用法说明
组件之间事件触发 新增按钮组件: 操作按钮组合组件: 此时有个需求就是,无论是哪个按钮,如果改变了列表中的数据,列表需要实时更新数据. 此时就需要用到组件间的事件触发. 父子组件之间事件触发可以使用$ ...
- File类----> FileFilter接口:实现方法
1创建一个类 继承 FileFilter接口 在类中重写boolean accept方法 写出要实现的条件2在main方法中创建File对象 代表了D盘File file = new File(&qu ...
- js实现指定dom节点滚动到可视窗口
const rollDom = document.getElementById('domId') // 获取想要滚动的dom节点 rollDom.scrollIntoView({ block: 'ce ...
- Android studio SDK配置
因为两个月前装过一次Android studio,所以完全按教程走不通. 已有Android studio的情况下,先在configue下配置SDK的位置,这里可能会报一个错,platforms不存在 ...