docker-compose 中的 Kafka Streams 需要很长时间进行分区分配
Kafka Streams in docker-compose takes long time for partition assignment
我是 运行 docker 容器中的 Kafka 流应用程序。出于测试目的,我有一个 docker-compose 文件,它运行流应用程序、kafka 的单个实例和 zookeeper。 kafka 和 zookeeper 的配置以前都有效。
kafka streaming应用程序分配分区需要5分钟以上。如果我延迟 运行 流容器直到 kafka 和 zookeeper 启动,并且流应用程序正在使用的主题已正确实例化,那么它几乎立即获得分配的分区。
似乎正在实例化 kafka 流组,但是,没有为应用程序分配任何分区。这大概是因为主题尚未完全实例化。它直到下一代才分配分区,这似乎几乎需要 5 分钟。
根据我对情况的(有限)了解,我有几个减少延迟的选项:
- 在启动流应用程序之前检查主题是否有元数据
- 减少世代之间的间隔(似乎这在生产中可能会有问题,但可能适合测试)
但是,考虑到我在这方面的知识有限,我意识到我可能遗漏了一些明显的东西。
编辑:docker-撰写文件供参考
version: 3.3
services:
kafka-stream-ingestor:
build:
context: .
dockerfile: Dockerfile
args:
- version
networks:
- services
zookeeper:
image: wurstmeister/zookeeper
ports:
- 2181:2181
networks:
- services
kafka:
image: wurstmeister/kafka:latest
ports:
- 9094:9094
- 9092:9092
environment:
KAFKA_ADVERTISED_HOST_NAME: ${DOCKER_KAFKA_HOST}
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_ADVERTISED_PROTOCOL_NAME: OUTSIDE
KAFKA_ADVERTISED_PORT: 9094
KAFKA_CREATE_TOPICS: "kafka-queue:12:1"
KAFKA_PROTOCOL_NAME: INSIDE
KAFKA_PORT: 9092
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- services
networks:
services:
volumes:
testresult:
我找到了一个在有限情况下有效的临时解决方案(仅在本地测试或通过集成测试时需要)。我不会将其标记为已解决,以便提供更好的答案。
基本上,流应用程序在分区准备好之前要求元数据。 kafka 说 'there are no partitions yet' 而应用程序说 'okay there are no partitions for assignment',然后等待一段(可配置的)时间,直到分区元数据变得陈旧。然后它向 kafka 发出另一个请求,此时已经创建了分区。
决定此刷新间隔的配置是 kafka.metadata.max.age.ms
。我将其设置为 1000 毫秒。
我是 运行 docker 容器中的 Kafka 流应用程序。出于测试目的,我有一个 docker-compose 文件,它运行流应用程序、kafka 的单个实例和 zookeeper。 kafka 和 zookeeper 的配置以前都有效。
kafka streaming应用程序分配分区需要5分钟以上。如果我延迟 运行 流容器直到 kafka 和 zookeeper 启动,并且流应用程序正在使用的主题已正确实例化,那么它几乎立即获得分配的分区。
似乎正在实例化 kafka 流组,但是,没有为应用程序分配任何分区。这大概是因为主题尚未完全实例化。它直到下一代才分配分区,这似乎几乎需要 5 分钟。
根据我对情况的(有限)了解,我有几个减少延迟的选项:
- 在启动流应用程序之前检查主题是否有元数据
- 减少世代之间的间隔(似乎这在生产中可能会有问题,但可能适合测试)
但是,考虑到我在这方面的知识有限,我意识到我可能遗漏了一些明显的东西。
编辑:docker-撰写文件供参考
version: 3.3
services:
kafka-stream-ingestor:
build:
context: .
dockerfile: Dockerfile
args:
- version
networks:
- services
zookeeper:
image: wurstmeister/zookeeper
ports:
- 2181:2181
networks:
- services
kafka:
image: wurstmeister/kafka:latest
ports:
- 9094:9094
- 9092:9092
environment:
KAFKA_ADVERTISED_HOST_NAME: ${DOCKER_KAFKA_HOST}
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_ADVERTISED_PROTOCOL_NAME: OUTSIDE
KAFKA_ADVERTISED_PORT: 9094
KAFKA_CREATE_TOPICS: "kafka-queue:12:1"
KAFKA_PROTOCOL_NAME: INSIDE
KAFKA_PORT: 9092
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- services
networks:
services:
volumes:
testresult:
我找到了一个在有限情况下有效的临时解决方案(仅在本地测试或通过集成测试时需要)。我不会将其标记为已解决,以便提供更好的答案。
基本上,流应用程序在分区准备好之前要求元数据。 kafka 说 'there are no partitions yet' 而应用程序说 'okay there are no partitions for assignment',然后等待一段(可配置的)时间,直到分区元数据变得陈旧。然后它向 kafka 发出另一个请求,此时已经创建了分区。
决定此刷新间隔的配置是 kafka.metadata.max.age.ms
。我将其设置为 1000 毫秒。