最近搭建 kafka 集羣環境以便於收集應用程序日誌並進行個性化的處理,因此學習了 kafka 生產者和消費者 python 程序的實現。這篇文章當是 kafka 的學習筆記。
一、搭建 kafka 集羣
爲方便測試,我們在 MacOS 單機上搭建具有三個 kafka 節點的集羣。如果在生產上部署 kafka ,請在不同的物理機上部署 kafka 集羣。
1. 下載 kafka 鏡像
我們使用 wurstmeister/kafka 鏡像來部署 kafka,由於 kafka 依賴於 zookeeper ,因此,我們需要下載 zookeeper 和 kafka 兩個鏡像。
docker pull wurstmeister/kafka
docker pull wurstmeister/zookeeper
2. 編寫 docker-compopse.yml
我們搭建的 kafka 集羣包括一個 zooker 節點和三個 kakfa 節點。
使用 ifconfig
命令獲取本機的 ip 爲 192.168.0.104
,完整的 docker-compose.yml 文件如下。有關 docker-compose 的使用,可以參考 《Docker Compose 入門教程》。
version: '3'
services:
zookeeper:
image: docker.io/wurstmeister/zookeeper
container_name: zookeeper
restart: always
ports:
- "2181:2181"
kafka1:
image: docker.io/wurstmeister/kafka
container_name: kafka1
restart: always
ports:
- "9095:9092"
depends_on:
- zookeeper
environment:
KAFKA_BROKER_ID: 0
KAFKA_ZOOKEEPER_CONNECT: 192.168.0.104:2181
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.0.104:9095
kafka2:
image: docker.io/wurstmeister/kafka
container_name: kafka2
restart: always
ports:
- "9096:9093"
depends_on:
- zookeeper
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: 192.168.0.104:2181
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9093
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.0.104:9096
kafka3:
image: docker.io/wurstmeister/kafka
container_name: kafka3
restart: always
ports:
- "9097:9094"
depends_on:
- zookeeper
environment:
KAFKA_BROKER_ID: 2
KAFKA_ZOOKEEPER_CONNECT: 192.168.0.104:2181
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9094
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.0.104:9097
使用 docker-compose up -d
運行相關的容器,完成 kafka 集羣的搭建。
二、Kafka 生產者
我們使用 kafka-python
包來編寫 kafka 生產者。使用以下命令下載 kafka-python
包:
pip install kafka-python
Kafka 生產者的源代碼如下:
from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers=["192.168.0.104:9095", '192.168.0.104:9096', '192.168.0.104:9097'])
for _ in range(10):
producer.send('topic_test', b'hello kafka')
producer.flush()
先創建一個 KafkaProducer
對象 producer
,KafkaProducer
指定了 kafka 集羣各個節點的地址。然後通過 KafkaProducer
對象向 topic topic_test
發送消息。
三、Kafka 消費者
爲接收生產者的消息,我們定義消費者 KafkaConsumer
對象 consumer
。定義 KafkaConsumer
對象時,指定 topic 爲 topic_test
,這樣當運行上面的生產者程序時,可以正常接收到消息。
from kafka import KafkaConsumer
consumer = KafkaConsumer('topic_test', group_id="my_group", bootstrap_servers=["192.168.0.104:9095", '192.168.0.104:9096', '192.168.0.104:9097'])
for msg in consumer:
print(msg.value)
先運行消費者程序,再運行生產者程序,可以看到消費者程序輸出:
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
多個消費者
如果需要啓動多個消費者來消費生產者發送的消息,並實現負載均衡,可以爲 topic 設置多個 partition。爲方便起見,我們設置 topic 的 partition 數量與消費者數量均爲 2。
進入其中一個 kafka 容器:
docker exec -it kafka1 /bin/bash
在容器內,查看topic_test
的 partition 數量:
cd /opt/kafka
bin/kafka-topics.sh --describe --zookeeper 192.168.0.104:2181 --topic topic_test
可以看到 topic_test
的 partition 數量爲 1。修改 topic_test
partition 數量爲 2:
bin/kafka-topics.sh --zookeeper 192.168.0.104:2181 --alter --topic topic_test --partitions 2
啓動兩個消費者程序,然後啓動一個生產者程序,可以看到,其中一個消費者輸出:
b’hello kafka’
b’hello kafka’
b’hello kafka’
另一個消費者輸出:
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
b’hello kafka’
生產者發送的消息被兩個消費者進行了消費,不同的消費者接收到的消息數量不一致,這是由於使用了默認的負載均衡策略所致。多次運行生產者程序,可以看到消費者接收到的總的消息數量基本上一致。
參考資料
- http://kafka.apache.org/
- http://wurstmeister.github.io/kafka-docker/
- https://www.cnblogs.com/answerThe/p/11267129.html
- https://www.jianshu.com/p/fe73765ef74d
- https://pypi.org/project/kafka-python/
- https://www.cnblogs.com/small-office/p/9399907.html