Kafka 中的数据怎么可能在容器回收中幸存下来?
How is it possible that data in Kafka survives container recycling?
首先,我不知道这个问题是与卡夫卡有关还是与Docker有关……我对这两个主题都是菜鸟。但我认为它更像是一个 Docker 而不是 Kafka 问题(事实上,我的问题不是真正理解其中一个问题……)。
我在 Raspberry 4 上安装了 Docker 并为 Kafka 和 Zookeeper 创建了 Docker 图像;我必须自己创建它们,因为任何现有图像都不支持 64 位 Raspi(至少我找不到任何图像)。但我让他们工作了。
接下来我实现了 Kafka 文档中的 Kafka Streams 示例 (Wordcount);它运行良好,计算你输入的所有文本中的单词,保留所有先前运行的数字。这是意料之中的事;至少在该文档中是这样描述的。
所以在一些测试运行之后我想重置整个东西。
我认为最简单的方法是关闭 docker 容器,删除主机上安装的文件夹并重新开始。
但这不起作用:计数器这个词仍然存在!意思是字数不是从0开始的……
好的,下一个回合:不仅要删除容器,还要重建镜像!当然是 Zookeeper 和 Kafka!
没有区别!保留所有先前运行的字数。
使用 docker system prune --volumes
也没有区别……
根据我对 Docker 的有限理解,我假设任何运行时数据都存储在容器中,或者存储在挂载的文件夹(卷)中。因此,当我删除 Docker 主机上由容器装载的容器和文件夹时,我预计任何状态都会消失。
显然不是……所以我在这里漏掉了一些重要的东西,很可能是 Docker。
我使用的docker-compose文件:
version: '3'
services:
zookeeper:
image: tquadrat/zookeeper:latest
ports:
- "2181:2181"
- "2888:2888"
- "3888:3888"
- "8080:8080"
volumes:
- /data/zookeeper/config:/config
- /data/zookeeper/data:/data
- /data/zookeeper/datalog:/datalog
- /data/zookeeper/logs:/logs
environment:
ZOO_SERVERS: "server.1=zookeeper:2888:3888;2181"
restart: always
kafka:
image: tquadrat/kafka:latest
depends_on:
- zookeeper
ports:
- "9091:9091"
volumes:
- /data/kafka/config:/config
- /data/kafka/logs:/logs
environment:
KAFKA_LISTENERS: "INTERNAL://kafka:29091,EXTERNAL://:9091"
KAFKA_ADVERTISED_LISTENERS: "INTERNAL://kafka:29091,EXTERNAL://TCON-PI4003:9091"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT"
KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL"
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_DELETE_TOPIC_ENABLE: "true"
restart: always
我用来清除挂载文件夹的脚本文件:
#!/bin/sh
set -eux
DATA="/data"
KAFKA_DATA="$DATA/kafka"
ZOOKEEPER_DATA="$DATA/zookeeper"
sudo rm -R "$KAFKA_DATA"
sudo rm -R "$ZOOKEEPER_DATA"
mkdir -p "$KAFKA_DATA/config" "$KAFKA_DATA/logs"
mkdir -p "$ZOOKEEPER_DATA/config" "$ZOOKEEPER_DATA/data" "$ZOOKEEPER_DATA/datalog" "$ZOOKEEPER_DATA/logs"
有什么想法吗?
Kafka Streams 在 运行 所在的主机上的 "state.dir"
配置下存储自己的状态。在 Apache Kafka 库中,它位于 /tmp
下。首先检查您是否在代码中覆盖了 属性 。
就Docker而言,先尝试不使用卷。
Using docker system prune --volumes made no difference also …
这将清除在 Compose 中使用 docker volume create
或 volumes:
创建的未附加卷,而不是主机挂载的目录。
正如我从一开始就假设的那样,问题主要是我缺乏知识。
我观察到的行为与 Docker 的魔法数据存储无关,该数据存储在所有试图杀死它的尝试中都幸存下来;它与 Docker 完全无关。
我将那些 Docker 图像用于 运行 Zookeeper 和上面的 Kafka 服务器。然后我切换回我的工作站机器,编写了实现 Kafka 流处理器的代码("Wordcount" 示例)。当我在 IDE 中启动它时,它是在我的本地计算机上执行的,通过网络访问 Kafka。
我的假设是 any 状态存储在 Kafka 服务器上,因此应该重置整个事情的转储;因为那不起作用,我也抛弃了 Zookeeper,因为这也无济于事,我几乎删除了所有东西……
在这里得到一些提示后,我发现 Kafka Streams 处理器在通过 state.dir
(StreamsConfig.STATE_DIR_CONFIG
) 配置的文件系统文件夹中维护自己的本地状态 – 请参阅 Configuring a Streams Application。这意味着 Kafka Streams 处理器维护其 自己的本地 状态 独立 来自任何 Kafka 服务器,并且 - 就像我的情况一样 运行s 在我的本地机器上 – 也 outside/unrelated 到任何 Docker 容器…
根据文档,默认位置应该是 /var/lib/kafka-streams
,但这在我的环境中是不可写的——不知道流处理器把它的状态放在哪里。
将我的 Streams 处理器的配置值 state.dir
显式设置到我的主目录中的一个文件夹后,我可以在我的磁盘上看到该状态,删除它后,字数统计从 1 重新开始。
深入查看 Kafka Streams 的文档后发现,在启动流处理器之前或关闭流处理器之后调用 KafkaStream.cleanup()
也可以获得相同的结果(不需要删除文件系统上的文件)。
首先,我不知道这个问题是与卡夫卡有关还是与Docker有关……我对这两个主题都是菜鸟。但我认为它更像是一个 Docker 而不是 Kafka 问题(事实上,我的问题不是真正理解其中一个问题……)。
我在 Raspberry 4 上安装了 Docker 并为 Kafka 和 Zookeeper 创建了 Docker 图像;我必须自己创建它们,因为任何现有图像都不支持 64 位 Raspi(至少我找不到任何图像)。但我让他们工作了。
接下来我实现了 Kafka 文档中的 Kafka Streams 示例 (Wordcount);它运行良好,计算你输入的所有文本中的单词,保留所有先前运行的数字。这是意料之中的事;至少在该文档中是这样描述的。
所以在一些测试运行之后我想重置整个东西。
我认为最简单的方法是关闭 docker 容器,删除主机上安装的文件夹并重新开始。
但这不起作用:计数器这个词仍然存在!意思是字数不是从0开始的……
好的,下一个回合:不仅要删除容器,还要重建镜像!当然是 Zookeeper 和 Kafka!
没有区别!保留所有先前运行的字数。
使用 docker system prune --volumes
也没有区别……
根据我对 Docker 的有限理解,我假设任何运行时数据都存储在容器中,或者存储在挂载的文件夹(卷)中。因此,当我删除 Docker 主机上由容器装载的容器和文件夹时,我预计任何状态都会消失。
显然不是……所以我在这里漏掉了一些重要的东西,很可能是 Docker。
我使用的docker-compose文件:
version: '3'
services:
zookeeper:
image: tquadrat/zookeeper:latest
ports:
- "2181:2181"
- "2888:2888"
- "3888:3888"
- "8080:8080"
volumes:
- /data/zookeeper/config:/config
- /data/zookeeper/data:/data
- /data/zookeeper/datalog:/datalog
- /data/zookeeper/logs:/logs
environment:
ZOO_SERVERS: "server.1=zookeeper:2888:3888;2181"
restart: always
kafka:
image: tquadrat/kafka:latest
depends_on:
- zookeeper
ports:
- "9091:9091"
volumes:
- /data/kafka/config:/config
- /data/kafka/logs:/logs
environment:
KAFKA_LISTENERS: "INTERNAL://kafka:29091,EXTERNAL://:9091"
KAFKA_ADVERTISED_LISTENERS: "INTERNAL://kafka:29091,EXTERNAL://TCON-PI4003:9091"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT"
KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL"
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_DELETE_TOPIC_ENABLE: "true"
restart: always
我用来清除挂载文件夹的脚本文件:
#!/bin/sh
set -eux
DATA="/data"
KAFKA_DATA="$DATA/kafka"
ZOOKEEPER_DATA="$DATA/zookeeper"
sudo rm -R "$KAFKA_DATA"
sudo rm -R "$ZOOKEEPER_DATA"
mkdir -p "$KAFKA_DATA/config" "$KAFKA_DATA/logs"
mkdir -p "$ZOOKEEPER_DATA/config" "$ZOOKEEPER_DATA/data" "$ZOOKEEPER_DATA/datalog" "$ZOOKEEPER_DATA/logs"
有什么想法吗?
Kafka Streams 在 运行 所在的主机上的 "state.dir"
配置下存储自己的状态。在 Apache Kafka 库中,它位于 /tmp
下。首先检查您是否在代码中覆盖了 属性 。
就Docker而言,先尝试不使用卷。
Using docker system prune --volumes made no difference also …
这将清除在 Compose 中使用 docker volume create
或 volumes:
创建的未附加卷,而不是主机挂载的目录。
正如我从一开始就假设的那样,问题主要是我缺乏知识。
我观察到的行为与 Docker 的魔法数据存储无关,该数据存储在所有试图杀死它的尝试中都幸存下来;它与 Docker 完全无关。
我将那些 Docker 图像用于 运行 Zookeeper 和上面的 Kafka 服务器。然后我切换回我的工作站机器,编写了实现 Kafka 流处理器的代码("Wordcount" 示例)。当我在 IDE 中启动它时,它是在我的本地计算机上执行的,通过网络访问 Kafka。
我的假设是 any 状态存储在 Kafka 服务器上,因此应该重置整个事情的转储;因为那不起作用,我也抛弃了 Zookeeper,因为这也无济于事,我几乎删除了所有东西……
在这里得到一些提示后,我发现 Kafka Streams 处理器在通过 state.dir
(StreamsConfig.STATE_DIR_CONFIG
) 配置的文件系统文件夹中维护自己的本地状态 – 请参阅 Configuring a Streams Application。这意味着 Kafka Streams 处理器维护其 自己的本地 状态 独立 来自任何 Kafka 服务器,并且 - 就像我的情况一样 运行s 在我的本地机器上 – 也 outside/unrelated 到任何 Docker 容器…
根据文档,默认位置应该是 /var/lib/kafka-streams
,但这在我的环境中是不可写的——不知道流处理器把它的状态放在哪里。
将我的 Streams 处理器的配置值 state.dir
显式设置到我的主目录中的一个文件夹后,我可以在我的磁盘上看到该状态,删除它后,字数统计从 1 重新开始。
深入查看 Kafka Streams 的文档后发现,在启动流处理器之前或关闭流处理器之后调用 KafkaStream.cleanup()
也可以获得相同的结果(不需要删除文件系统上的文件)。