作者:Each+ Apollo
文章目录
1.kafka
1.1. 什么是kafka
Kafka 是一种高吞吐量的分布式发布订阅消息系统,有如下特性:
- 通过O(1)的磁盘数据结构提供消息的持久化,这种结构对于即使数以TB的消息存储也能够保持长时间的稳定性能。
- 高吞吐量:即使是非常普通的硬件Kafka也可以支持每秒数百万的消息。
- 支持通过Kafka服务器和消费机集群来分区消息。
1.2. 使用docker安装kafka
# 下载zookeeper镜像
docker pull wurstmeister/zookeeper
# 下载kafka镜像
docker pull wurstmeister/kafka
# 启动zookeeper
docker run -d --name zookeeper --publish 2181:2181 --volume /etc/localtime:/etc/localtime wurstmeister/zookeeper
# 启动kafka
docker run -d --name kafka3 --publish 9092:9092 --link zookeeper --env KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 --env KAFKA_ADVERTISED_HOST_NAME=127.0.0.1 --env KAFKA_ADVERTISED_PORT=9092 wurstmeister/kafka
1.3. 测试kafka是否正常
- 首先打开两个命令框,都进入kafka容器内
docker exec -it kafka容器id /bin/bash
- 然后一个命令框测试生成消息
/opt/kafka/bin/kafka-topics.sh --zookeeper zookeeper:2181 --describe --topic test1
/opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test1
- 另一个命令框测试接收消息
/opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic test1 --from-beginning
- 这时候在发送端命令框内输入任意消息,回车,在接收方内会受到消息
2. aiokafka
2.1. 简单的理解
aiokafka是python的一个第三方库,可以连接kafka并实现异步收发消息,性能非常强大,因为集成了async。
2.2. 安装
pip3 install aiokafka
2.3. AIOKafkaProducer(**kwargs) 生产者(发消息)
2.3.1. 常用参数
- loop: 协程循环事件
- bootstrap_servers:ip端口链接池,可以多个
其他参数可以进入到这个类中查看,写的非常详细
2.3.2. send_and_wait(topic, **kwargs)生产消息
参数:
- topic:主题
- key:键名,二进制
- value:值,二进制
2.3.3. stop() 关闭连接
断开和kafka的连接
2.3.3. 举个栗子
from aiokafka import AIOKafkaProducer
import asyncio
async def main(loop):
### 初始化
producer = AIOKafkaProducer(
loop=loop,
bootstrap_servers=["127.0.0.1:9092"],
api_version="auto",
)
### 启动
await producer.start()
### 生成消息
await producer.send_and_wait(
"my_topic",
key="Each+ Apollo".encode(),
value="is nice".encode(),
)
### 断开连接
await producer.stop()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
想要接受消息,需要用到下面的内容
2.4. AIOKafkaConsumer(topic, **kwargs) 消费者(收消息)
2.4.1. 常用参数
- topic:主题,需要和生产者的topic保持一致,不然收不到正确消息
- group_id:消费者的组别,可以是任意的,但是不要重复
- auto_offset_reset:收消息的模式,“earliest”, “latest”,默认是后者
- loop: 协程循环事件
- bootstrap_servers:ip端口连接池
- metadata_max_age_ms:强制刷新事件,单位毫秒
其他参数可以进入该类中查看,有详细介绍
2.4.2. getmany() 读取消息
- 若没有消息,得到空字典
- 若有一条或多条消息,得到以TopicPartition对象为键,以ConsumerRecode对象组成的列表为值的字典
2.4.3. TopicPartition对象
取出topic
# tp = TopicPartition(topic='my_topic', partition=0)
tp.topic
2.4.4. ConsumerRecode对象
ConsumerRecord(topic=‘my_topic’, partition=0, offset=37, timestamp=1614593594258, timestamp_type=0, key=b’Each+ Apollo’, value=b’is nice’, checksum=None, serialized_key_size=12, serialized_value_size=7, headers=())
- offset: 消息号,是递增的,不重复
- key:键
- value:值
- timestamp:时间戳
msg.value
msg.key
msg.offset
......
2.4.5. 举个栗子
import asyncio
from aiokafka import AIOKafkaConsumer
async def main(loop):
### 初始化消费者
consumer = AIOKafkaConsumer(
"my_topic",
group_id='aaaa',
loop=loop,
auto_offset_reset='earliest',
bootstrap_servers=["127.0.0.1:9092"],
api_version="auto",
metadata_max_age_ms=(30 * 1000),
)
### 连接
await consumer.start()
### 获取消息
data = await consumer.getmany()
print(data)
if data:
for tp, message in data.items():
print('tp>>>', tp)
print(tp.topic)
print('message>>', message)
for msg in message:
print(msg)
print(msg.timestamp, msg.offset)
v = msg.value
print(v)
### 断开
await consumer.stop()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
2.4.6. 循环接收消息
一般我们把消费者的getmany等逻辑放在while循环里,每隔1秒或0.5秒执行一次,就是简单的监听消息队列逻辑了。