介绍
RabbitMQ是一个消息中间人:它接收消息、传递消息。你可以把它看作邮局——你将邮件放到邮箱,你可以确定邮递员先生(女士)最终会将这封邮件交到你的收件人手里。按照这个推论,RabbitMQ是一个邮箱、邮局和邮递员的集合。
RabbitMQ和邮局之间最大的不同就是它不处理不纸张信件,而是处理二进制消息数据块。RabbitMQ和一般的消息中间人都用一些行话(术语):
- Producer(生产者),生产无非就是发送。发送消息的进程成为生产者
- Queue(队列),你可以理解为RabbitMQ内部的邮箱。消息在RabbitMQ和你的应用之间时,他们被保存在队列中。队列收到主机内存和磁盘的限制,它本质上是一个巨大的消息缓冲区。多个生产者可以发送消息到一个队列;多个消费者也乐意从一个队列接收数据。
- Consumer(消费者),消费/接收消息的进程称为消费者
RabbitMQ Server 安装
本教程采用Docker安装RabbitMQ,单节点方式
预备要求:
一台安装了Docker服务的主机
docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5671:5671 rabbitmq:3-management# 访问 host-ip:15672即可访问rabbitmq管理界面,默认登录 账号/密码:guest/guest# host-ip:5671 是rabbitmq连接的端口
Hello World
安装
pip install pika --upgrade
send.py
import pika# 初始化/建立连接(establish a connection)# connection_url = 'amqp://{user}:{password}@{hostname}:{post}/{vhost}/?{各种参数}'connection_url = 'amqp://guest:guest@localhost:5671/test/?heartbeat=0'connection = pika.BlockingConnection(pika.URLParameters(connection_url))# 我们连接上了一个中间件,生成一个channelchannel = connection.channel()# 在发送消息之前,我们需要确保接收队列存在。如果我们发送该消息时,对应的队列不存在,rabbitmq将会直接丢弃这个消息。所以在发送消息前要先创建队列channel.queue_declare(queue='hello') # 声明hello队列
这样就准备好一个队列了,我们可以发送消息了现在。
但是RabbitMQ不会把消息直接发送到队列,队列需要经过一个交换机(exchange,暂时我们不要被这些细节所拖累,后续章节会有更详细的介绍)。我们现在所要知道的是如何使用默认交换机(
exchange=''
)。这个交换机的特殊之处在于它允许我们指定消息将要去往的队列。对立需要使用routing_key
参数指定,如下channel.basic_publish(exchange='', routing_key='hello', body='Hello World!')print(" [x] Sent 'Hello World!'")# 在我们退出程序之前,我们需要确认网络缓冲区被刷新并且我们的消息被准确地递交给rabbitmq。要做到这些,我们只需优雅的关闭连接,如下connection.close()
提醒:如果你是第一次使用RabbitMQ,并且你发现"Sent"消息没有出现,也许是中间人所在的主机没有足够的空闲磁盘空间。如果rabbit可用磁盘空间少于200M,会拒绝消息。
receive.py
import pika# 初始化/建立连接(establish a connection)connection_url = 'amqp://{user}:{password}@{hostname}:{post}/{vhost}/?{各种参数}'connection = pika.BlockingConnection(pika.URLParameters(connection_url))# 我们连接上了一个中间件,生成一个channelchannel = connection.channel()# 我们不能确认send和receive这两个程序哪个先运行,所以这里要再声明一次队列channel.queue_declare(queue='hello')# 接收消息比较复杂,通过向队列订阅一个 回调 函数工作。任何时候 callback 函数都会被 Pika 库调用。def callback(ch, method, properties, body): print(" [x] Received %r" % body)# 接下来我们要告诉RabbitMQ这是一个特殊的 callback 函数,这个函数需要接收 hello 队列的消息。注意这里需要确认 此队列存在,这也是我们需要在 send 和 receive 两个程序中都声明该 队列的原因channel.basic_consume(queue='hello', auto_ack=True, on_message_callback=callback)print(' [*] Waiting for messages. To exit press CTRL+C')channel.start_consuming()
这里
auto_ack
参数为true
时,关闭手动信息确认。通常情况下,这个参数默认为false
,也就是说我们通常情况下需要手动确认信息。手动确认信息后面的内容专门讨论,所以这里我们选择关闭。现在我们依次执行这两个文件,将得到下面的结果
python send.py# => [x] Sent 'Hello World!'
python receive.py# => [*] Waiting for messages. To exit press CTRL+C# => [x] Received 'Hello World!'
预告: 《RabbitMQ工作队列》
长按关注,每天多一点了解