RabbitMQ 简介及例子(Python)

简介

RabbitMQ 是一个消息中间件(message broker)。它的核心思想很简单:接收和发送消息。你可以把它想象成一个邮局:当你寄信,把信投到邮箱里时,你确信一定有邮递员把信取走并送到收件人手中。RabbitMQ就可以比作邮箱+邮局+邮递员。

当然,RabbitMQ 和邮局最重要的区别是,它存储、发送的不是信件,而是二进制的数据——消息。

RabbitMQ在使用中有一些术语。

  • *“生产者”*其实和“消息发送”意思差不多。一个可以发送消息的程序叫做生产者:
    在这里插入图片描述
  • 一个队列可以比喻作是一个邮箱,包含在RabbitMQ里。虽然消息的传输需要通过RabbitMQ和你的应用程序,但这些消息只能保存在队列中。一个队列是没有什么约束和限制的,只要你愿意它可以存储很多消息,本质上来说它就是一个无穷的缓冲区。多个消息生产者可以向一个队列发送消息,同样多个消费者可以尝试接收一个队列中的消息。下图所示就是一个队列:
    在这里插入图片描述
  • 消费也可以理解为接收。一个接收者就是一个等待接收消息的程序。下图就是一个接受者“C”:
    在这里插入图片描述
    注意:生产者、消费者、中间件不必在同一台机器上。而且在多数应用场景下,他们没有在一台机器上。一个应用也可以同时是生产者和消费者。

Hello World!

(运用Python中的Pika库)

在这个案例中,我们要用Python写两个小程序,一个负责发送一条消息的生产者,和一个负责接收消息并输出的消费者。消息内容是“Hello World”。

在下图中,“P”是生产者,“C”是消费者。中间是一个队列——也就是RabbitMQ为生产者保留信息的信息缓冲区。
在这里插入图片描述
生产者向队列发送“hello”,消费者从队列接收消息。

安装Pika库

可通过下面的语句安装:

python -m pip install pika --upgrade 

装好Pika库后,就可以写程序了。

Sending

在这里插入图片描述
我们的程序send.py将给队列发送一条消息。首先我们要建立和RabbitMQ的连接。

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

现在,我们已连接到本地计算机上的代理 - localhost。如果我们想连接到另一台计算机上的代理,则只需在此处改成其名称或IP地址。

接下来,在发送之前,我们需要确保收件人队列存在。如果我们将消息发送到不存在的位置,RabbitMQ只会删除该消息。让我们创建一个 hello 的消息队列:

channel.queue_declare(queue='hello')

这个时候,我们已经准备好发送一条消息了。我们的第一条消息是 Hello World! 字符串,将它发送到 hello 队列。

在RabbitMQ中,我们不能直接向队列发送消息,它需要经过 exchange 的步骤。在这里就不赘述,详见第三章。现在我们只需知道默认的 exchange 就是空字符串的形式。这种 exchange 很特别 —— 它允许我们指定消息要去哪个特定的队列。这个队列的名称写在routing_key参数中:

channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='Hello World!')
print(" [x] Sent 'Hello World!'")

在退出程序之前,我们需要确保网络缓冲区已刷新并且消息已传递到RabbitMQ。 我们可以通过关闭连接来实现它。

connection.close()

无法发送!

如果这是你第一次使用RabbitMQ并且你没有看到“Sent”出的消息,可能的原因是中间件没有足够的磁盘空间(默认最少需要200MB的磁盘空间),从而拒绝接收消息。检查中间件(broker)的日志文件,必要时减少一些限制。此文件帮助你如何设置disk_free_limit

Receiving

在这里插入图片描述
第二个程序receive.py将会从队列中接收消息并打印在屏幕上。

我们首先要做的依然是连接RabbitMQ服务器,实现代码同上。

下一步,我们依然是要确保队列存在,用queue_declare是幂等的 —— 我们可以运行好多次,但只会生成一个。

channel.queue_declare(queue='hello')

你可能会疑惑为什么再次声明队列 —— 我们已经在先前的代码中声明了它。 如果我们确定队列已经存在,那么就可以省略它,例如如果之前运行过send.py程序。 但是,我们尚不确定哪个程序先运行。 在这种情况下,最好在两个程序中重复声明队列。

列出所有队列

你可能想知道目前RabbitMQ有哪些队列,这些队列又有多少消息。你可以用rabbitmqctl来查看:

sudo rabbitmqctl list_queues 

在Windows上,忽略 sudo:

rabbitmqctl.bat list_queues

从队列接收消息更为复杂。 它通过callback函数来工作。 每当我们收到消息时,Pika库都会调用此callback函数。 在这个例子中,此函数将在屏幕上打印消息的内容。

def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)

接下来,我们需要告诉RabbitMQ这个callback函数应该从 hello 队列接收消息:

channel.basic_consume(queue='hello',
                      auto_ack=True,
                      on_message_callback=callback)

为了使该命令成功执行,我们必须确保队列存在。 幸运的是,因为我们之前已经使用queue_declare创建了队列,我们可以确保队列是存在的。

auto_ack参数就在之后解释。

最终,我们形成一个无限循环,不断地等待数据并在需要的时候调用callback函数。

print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

最终代码

send.py(source)

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(
    pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

channel.queue_declare(queue='hello')

channel.basic_publish(exchange='', routing_key='hello', body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()

receive.py(source)

#!/usr/bin/env python
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()

现在我们可以在终端运行了。 首先,我们运行一个消费者,它将持续运行等待消息:

python receive.py
# => [*] Waiting for messages. To exit press CTRL+C
# => [x] Received 'Hello World!'

接着运行生产者。程序每次运行完成后就会停止:

python send.py
# => [x] Sent 'Hello World!'

太棒了! 我们通过RabbitMQ发送了第一条消息。 你可能注意到,receive.py程序不会退出。 它随时准备接收其他消息,你可以通过 Ctrl-C 中断。

尝试在新终端中再次运行send.py

我们已经学习了如何从一个命名的队列发送和接收消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值