私はdockerized Kafkaを使用しており、1つのKafkaコンシューマプログラムを記述しています。Kafkaをdockerとアプリケーションで実行すると、私のローカルマシンで。しかし、Dockerでローカルアプリケーションを構成すると、問題が発生します。この問題は、アプリケーションが起動するまでトピックが作成されないことが原因である可能性があります。
docker-compose.yml
version: '3'
services:
zookeeper:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
kafka:
image: wurstmeister/kafka
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_Host_NAME: localhost
KAFKA_CREATE_TOPICS: "test:1:1"
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
volumes:
- /var/run/docker.sock:/var/run/docker.sock
parse-engine:
build: .
depends_on:
- "kafka"
command: python parse-engine.py
ports:
- "5000:5000"
parse-engine.py
from kafka import KafkaConsumer
import json
try:
print('Welcome to parse engine')
consumer = KafkaConsumer('test', bootstrap_servers='localhost:9092')
for message in consumer:
print(message)
except Exception as e:
print(e)
# Logs the error appropriately.
pass
エラーログ
kafka_1 | [2018-09-21 06:27:17,400] INFO [SocketServer brokerId=1001] Started processors for 1 acceptors (kafka.network.SocketServer)
kafka_1 | [2018-09-21 06:27:17,404] INFO Kafka version : 2.0.0 (org.Apache.kafka.common.utils.AppInfoParser)
kafka_1 | [2018-09-21 06:27:17,404] INFO Kafka commitId : 3402a8361b734732 (org.Apache.kafka.common.utils.AppInfoParser)
kafka_1 | [2018-09-21 06:27:17,431] INFO [KafkaServer id=1001] started (kafka.server.KafkaServer)
**parse-engine_1 | Welcome to parse engine
parse-engine_1 | NoBrokersAvailable
parseengine_parse-engine_1 exited with code 0**
kafka_1 | creating topics: test:1:1
すでにdocker-composeにdepends_onプロパティを追加したので、トピックアプリケーションの接続を開始する前にエラーが発生しました。
私はdocker-composeファイルにスクリプトを追加できると読みましたが、簡単な方法を探しています。
手伝ってくれてありがとう
あなたの問題はネットワークです。あなたのKafka設定であなたが設定している
KAFKA_ADVERTISED_Host_NAME: localhost
しかし、これは、すべてのクライアント(pythonアプリを含む)がブローカーに接続し、ブローカーからすべての接続にlocalhost
を使用するように指示されることを意味します。クライアントマシン(例:pythonコンテナー)がブローカーの場所にない場合、リクエストは失敗します。
Kafkaリスナーの詳細については、こちらをご覧ください: https://rmoff.net/2018/08/02/kafka-listeners-explained/
したがって、問題を解決するには、次の2つのいずれかを実行します。
Kafka(KAFKA_ADVERTISED_Host_NAME: kafka
)のinternalホスト名を使用するように構成を変更するだけです。これは、すべてのクライアントwithindocker networkはそれにアクセスできますが、外部クライアントは(たとえば、ホストマシンから)できません):
version: '3'
services:
zookeeper:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
kafka:
image: wurstmeister/kafka
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_Host_NAME: kafka
KAFKA_CREATE_TOPICS: "test:1:1"
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
volumes:
- /var/run/docker.sock:/var/run/docker.sock
parse-engine:
build: .
depends_on:
- "kafka"
command: python parse-engine.py
ports:
- "5000:5000"
その後、クライアントはkafka:9092でブローカーにアクセスするため、pythonアプリは
consumer = KafkaConsumer('test', bootstrap_servers='kafka:9092')
新しいリスナーをカフカに追加します。これにより、Dockerネットワークの内部と外部の両方にアクセスできます。ポート29092は、(たとえば、ホストから)Dockerネットワークへのアクセスexternal用であり、internalアクセス用の9092です。
pythonプログラムを正しいアドレスにアクセスするためにKafkaに変更する必要があります。この場合、internalDockerネットワークでは、次を使用します。
consumer = KafkaConsumer('test', bootstrap_servers='kafka:9092')
私はwurstmeister
画像に慣れていないので、このdocker-composeは私が知っているConfluent画像に基づいています:
(編集者が私のyamlを壊した、あなたは見つけることができる ここにある )
---
version: '2'
services:
zookeeper:
image: confluentinc/cp-zookeeper:latest
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
kafka:
# "`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-
# An important note about accessing Kafka from clients on other machines:
# -----------------------------------------------------------------------
#
# The config used here exposes port 29092 for _external_ connections to the broker
# i.e. those from _outside_ the docker network. This could be from the Host machine
# running docker, or maybe further afield if you've got a more complicated setup.
# If the latter is true, you will need to change the value 'localhost' in
# KAFKA_ADVERTISED_LISTENERS to one that is resolvable to the docker Host from those
# remote clients
#
# For connections _internal_ to the docker network, such as from other services
# and components, use kafka:9092.
#
# See https://rmoff.net/2018/08/02/kafka-listeners-explained/ for details
# "`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-
#
image: confluentinc/cp-kafka:latest
depends_on:
- zookeeper
ports:
- 29092:29092
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_Host://localhost:29092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_Host:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
免責事項:私はConfluentに勤めています
この線
KAFKA_ADVERTISED_Host_NAME: localhost
ブローカーは自分自身をlocalhost
でのみ利用可能であると宣伝していると言います。つまり、すべてのKafkaクライアントは実際のブローカーアドレスの実際のリストではなく、自分自身のみを返します。これはクライアントがホストにのみ配置されている場合は問題ありません-リクエストは常にローカルホストに送信されますコンテナに転送されます。
ただし、他のコンテナー内のアプリの場合、Kafkaコンテナーを指す必要があるため、KAFKA_ADVERTISED_Host_NAME: kafka
、ここでkafka
はDocker Composeサービスの名前です。次に、他のコンテナのクライアントはそのコンテナに接続しようとします
とはいえ、この行は
consumer = KafkaConsumer('test', bootstrap_servers='localhost:9092')
あなたはPythonコンテナそれ自体を指しており、kafka
コンテナを指していない。
kafka:9092
代わりに