Docker に基づいて Python インターフェイスを使用して confluent-kafka を構築する
この記事では、docker とその Python インターフェイス上に構築された confluent-kafka の使用方法を紹介します。
この記事では、単一の Broker で confluent-kafka テスト環境のみを構築しますが、高可用性や高スループットなどの要素を考慮すると、正式な運用環境には通常、少なくとも 3 つのノードが必要です。
本稿で使用するシステム構成は次のとおりです。
- LinuxMint 20.3 (Ununtu 20.04 互換)
- ドッカー 20.10.21
- docker-compose 2.14.2
- Python 3.9.16
- converge-kafka(python包) 2.1.1
1. docker と docker-compose をインストールする
1.1 ドッカーをインストールする
docker-compose は docker に依存しているため、最初に docker をインストールする必要があります。
curl -fsSL https://test.docker.com -o test-docker.sh
sudo sh test-docker.sh
1.2 docker-compose をインストールする
Compose は、複数コンテナーの Docker アプリケーションを定義および実行するためのツールです。Compose を使用すると、YML ファイルを使用してアプリケーションに必要なすべてのサービスを構成できます。その後、1 つのコマンドで、YML ファイル構成からすべてのサービスを作成および開始できます。
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.14.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
他のバージョンの Compose をインストールするには、v2.14.2 を置き換えます。
2. confluent-kafka をインストールする
新しいファイルを作成し、docker-compose.yml ファイルを作成します。
version: '3'
services:
zookeeper:
image: confluentinc/cp-zookeeper:7.0.1
container_name: zookeeper
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
broker:
image: confluentinc/cp-kafka:7.0.1
container_name: broker
ports:
# To learn about configuring Kafka for access across networks see
# https://www.confluent.io/blog/kafka-client-cannot-connect-to-broker-on-aws-on-docker-etc/
- "9092:9092"
depends_on:
- zookeeper
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_INTERNAL:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092,PLAINTEXT_INTERNAL://broker:29092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
ここでローカル環境が構築されることに注意してください。ネットワークの別の場所から kafka にアクセスする必要がある場合は、KAFKA_ADVERTISED_LISTENERS
in をlocalhost
kafka が配置されているホストの実際のアドレス/ドメイン名に置き換える必要があります。
そのフォルダーに移動して、次を実行します。
docker-compose -f docker-compose.yml up -d
実行後、docker で同様の結果が表示され、起動が成功したことがわかります。
aa@bb:~/docker_scripts$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e6fbc05d61b1 confluentinc/cp-kafka:7.0.1 "/etc/confluent/dock…" 7 minutes ago Up 7 minutes 0.0.0.0:9092->9092/tcp, :::9092->9092/tcp broker
58b04385f2bf confluentinc/cp-zookeeper:7.0.1 "/etc/confluent/dock…" 7 minutes ago Up 7 minutes 2181/tcp, 2888/tcp, 3888/tcp zookeeper
ここで、kafka のポートは 9092 です。
コンテナ サービスをシャットダウンします。
docker-compose -f docker-compose.yml down
3. Python インターフェースの使用法
3.1 依存パッケージをインストールする
依存関係をインストールします。
pip3 install confluent-kafka
3.2 トピックの作成と表示
Kafka イメージを入力します。
docker exec -ti broker bash
トピックを表示:
[aa@bb ~]$ /bin/kafka-topics --list --bootstrap-server 127.0.0.1:9092
test001 という名前の新しいトピックを作成します。
[aa@bb ~]$ /bin/kafka-topics --create --bootstrap-server 127.0.0.1:9092 --topic test001 --partitions 2
Created topic test001.
トピックを表示:
[aa@bb ~]$ /bin/kafka-topics --list --bootstrap-server 127.0.0.1:9092
test001
Ctrl
+ P
+Q
をターミナルに戻します。
3.3 Python インターフェースブローカー
プロデューサー コードを作成しますproducer1.py
。
import socket
from confluent_kafka import Producer
conf = {
'bootstrap.servers': "localhost:9092",
'client.id': socket.gethostname()
}
producer = Producer(conf)
def __publish_delivery_report(err, msg) -> None:
if err is not None:
print(f"send msg:{
msg} fail, err is not None")
else:
print(f"send msg{
msg} success")
def send_msg(topic: str, data):
producer.produce(topic, data, callback=__publish_delivery_report)
producer.flush()
if __name__ == '__main__':
msg = "hello kafka"
topic = "test001"
send_msg(topic, msg)
操作結果:
aa@bb:~/codes/kafka_test$ python3 producer1.py
send msg<cimpl.Message object at 0x7f8d6fe6acc0> success
3.4 Python インターフェース - コンシューマー
コンシューマ コードを作成しますconsumer1.py
。
from confluent_kafka import Consumer
class KafkaConsumer:
def __init__(self, brokers, group):
config = dict()
config['bootstrap.servers'] = brokers
config['group.id'] = group
config['auto.offset.reset'] = 'earliest'
self.consumer = Consumer(config)
def subscribe(self, topics):
self.consumer.subscribe(topics=topics)
def pull(self):
while True:
msg = self.consumer.poll(1.0)
if msg is None:
continue
if msg.error():
print("Consumer error: {}".format(msg.error()))
continue
print('Received message: {}'.format(msg.value().decode('utf-8')))
def close(self):
self.consumer.close()
if __name__ == "__main__":
consumer = KafkaConsumer("127.0.0.1:9092", "test_group1")
consumer.subscribe(['test001'])
consumer.pull()
consumer.close()
操作結果:
aa@bb:~/codes/kafka_test$ python3 consumer1.py
Received message: hello kafka