准备
- 具有Python环境
- 能够连接到RabbitMq服务,并具有相应权限
- 使用 Pika Python Client。安装:
python -m pip install pika --upgrade
实现2个应用程序:
- 生产者发送Hello World
- 消费者接收并输出到屏幕
示意图如下:
通读该程序可以更加深入的理解RabbitMq的术语和使用流程。关于基本知识,请参考RabbitMq入门简介。
生产者
先上代码:
import pika
# 连接
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
# 建立通道
channel = connection.channel()
# 创建queue
channel.queue_declare(queue='hello')
# 发送
channel.basic_publish(exchange='', routing_key='hello', body='Hello World')
print("[x] Sent 'Hello World!'")
# 刷新流并关闭
connection.close()
流程分析:
- 连接。示例中连接到本地,端口、用户名、密码、vhost均为默认值。更通常的连接语句为:
credentials = pika.PlainCredentials('guest', 'guest')
parameters = pika.ConnectionParameters('127.0.0.1',
5672,
'/',
credentials)
connection = pika.BlockingConnection(parameters)
- 建立通道。通道是复用同一个连接的技术,后续操作都在该通道中进行。
- 声明队列。用于存储数据。在未创建队列时就发生数据,RabbitMq会丢弃数据。此处队列名为“hello”。
- 发送数据。我们知道,消息不能直接发送到队列,只能发送到Exchange。对于简单的应用,使用了空字符串的默认交换器,通过routing_key指定队列名,数据就发送到该处。
- 关闭:退出程序前,要刷新网络缓冲区确保数据已经发送给了RabbitMq。关闭连接时会自动执行该动作。
消费者
代码:
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')
# 回调处理数据
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
# 接收规则
channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
# 开始接收,不退出
channel.start_consuming()
详细说明:
- 连接和通道同前。
- 再次声明队列。
- 首先,多次声明队列不会产生任何影响,它是为了确保该队列的创建,hello只会被创建一次
- 其次,由于不能确保生产者总是先于消费者启动,所以消费者自行创建。这是一个良好的编程实践
- 回调函数。当接收到数据时,Pika库都会调用该回调函数。我们把接收到的数据输出到屏幕
- 接收规则
- 这是我自己起的名字,仅参考
- 它绑定了队列和回调函数,也就是说,该回调函数应该处理hello队列中接收的数据。或者说,当hello中有数据时,就会执行到callback
- 注意,如果执行该行时,队列未创建,就会执行失败。前面声明队列也是为了确保该函数执行成功
- auto_ack是否关闭发送消息已经消费的确认标识,类似于TCP中的ack确认,默认发送,此处为不发送
- 开始接收。进行循环等待接收数据的死循环。
运行效果
如前所述,先启动生产者会导致数据丢失。此处,先启动消费者,再启动生产者。结果如下:
消费者刚启动:
生产者:
此时的消费者:
注意:这个例程还有一些不足之处,如Exchange类别、ack、数据持久性等,我们会在后续文章中说明。