你好,世界
介绍
RabbitMQ是消息代理: 它接收并转发信息。举个例子: 小明从淘宝买了商品,配送员将快递投递到了快递柜, 小明再根据取件码去快递柜取快递。快递柜就相当于消息队列,快递员是生产者,小明是消费者。
-
生产者意味着发送, 所以发送信息的程序是生产者(Producer)。
-
尽管消息流经RabbitMQ和您的应用程序之中,但它们只能存储在队列之中, 甲队列仅由主机的存储器和磁盘限制和约束, 它本质上是一个大的消息缓冲器。许多生产者可以发送消息到同一个队列中,许多消费者可以尝试从一个队列中接收数据, 表示队列的方式。
-
消费与接收有相似的含义。消费者是一个程序,主要是等待接收信息。
生产者,消费者,消息队列不必位于同一主机上。一个应用程序既可以是消费者,也可以是生产者。
你好, 世界!
本部分内容中, 使用python编写两个小程序, 分别实现生产者和消费者。生产者进行数据发送,消费者进行数据接收并将其打印出来。
如图, P是生产者, 红色矩形相等于消息队列, C是消费者。 生产者将hello
发送到队列中, 消费者从队列中接收hello
。
RabbitMQ库
RabbitMQ使用多种协议。本教程使用AMQP 0-9-1,这是一种开放的通用消息传递协议。RabbitMQ有许多不同语言的客户。在本教程系列中,我们将使用Pika 1.0.0,这是RabbitMQ团队推荐的Python客户端。要安装它,您可以使用 pip包管理工具安装:
python -m pip install pika --upgrade
发送
- 我们第一个程序
send.py
需要向队列发送一条消息。需要做的第一件事是与RabbitMQ服务器建立连接。前提你已经安装了RabbitMQ
, 如果没有安装的话,可以参考我这篇博客使用Docker安装RabbitMQ。
from pika import BlockingConnection, ConnectionParameters
# RabbitMQ连接参数,基本有默认值
parameters = ConnectionParameters(
host='localhost',
# port=_DEFAULT,
# virtual_host=_DEFAULT,
# credentials=_DEFAULT,
# channel_max=_DEFAULT,
# frame_max=_DEFAULT,
# heartbeat=_DEFAULT,
# ssl_options=_DEFAULT,
# connection_attempts=_DEFAULT,
# retry_delay=_DEFAULT,
# socket_timeout=_DEFAULT,
# stack_timeout=_DEFAULT,
# locale=_DEFAULT,
# blocked_connection_timeout=_DEFAULT,
# client_properties=_DEFAULT,
# tcp_options=_DEFAULT,
)
connection = BlockingConnection(parameters=parameters)
channel = connection.channel()
-
接下来, 在发送之前, 我们需要确保收件人队列存在, 如果将消息发送到不存在的位置,RabbitMQ只会删除该消息。创建一个
hello
队列来信息消息传递:channel.queue_declare(queue='hello')
-
至此,准备发送消息了。第一个消息将字符串
Hello World!
发送到hello
队列中。在RabbitMQ中, 永远无法将消息直接发送到队列, 它始终需要进行交换,可以在本教程的发布/订阅部分中阅读相关信息。现在我们需要知道如何使用空字符串表示默认交换, 这种特殊的交换使我们可以准确的指定将信息发送到哪个队列。队列名称需要在
routing_key
参数中指定:channel.basic_publish(exchange='', routing_key='hello', body='Hello World!') print('已发送: Hello World!')
-
通过关闭连接来刷新网络缓存区:
connection.close()
接收
-
第二个程序
receive.py
将接收来自队列的消息并将其打印出来。 -
同样需要先连接
RabbitMQ
服务器, 负责连接RabbitMQ
的代码与之前代码相同。 -
像
send.py
一样,需要确保队列是否存在, 使用queue_declare
创建队列是幂等的, 可以根据需要多次使用该命令, 但是只会创建一个。channel.queue_declare(queue='hello')
在
send.py
中已经声明了该队列且已经运行,这里其实可以不用声明,但是考虑到不确定哪个程序先执行, 所以最好在两个程序中重复声明。 -
查看消息队列中有多少消息,
linux
下可以通过:rabbitmqctl list_queues
命令查看,windows通过rabbitmqctl.bat list_queues
查看。如果安装了web
控制台,登录之后可以切换到Queues
标签下查看。 -
接收消息比发生消息复杂一点, 通过回调函数来进行操作,当队列收到消息时会回调我们制定的消息处理函数。
def callback(ch, method, properties, body): """ :param ch: :param method: :param properties: :param body: :return: """ print("收到消息: {}".format(body))
-
接下来, 需要告诉队列指定回调函数和从哪个队列接收消息。
channel.basic_consume(queue='hello',
auto_ack=True,
on_message_callback=callback)
-
最后进入一个无限循环, 该循环等待数据并在必要的时候进行回调。
print('等待接收消息, 按CTRL+C退出....') channel.start_consuming()
代码整合
send.py
from pika import BlockingConnection, ConnectionParameters
# RabbitMQ连接参数,基本有默认值
parameters = ConnectionParameters(
host='localhost',
# port=_DEFAULT,
# virtual_host=_DEFAULT,
# credentials=_DEFAULT,
# channel_max=_DEFAULT,
# frame_max=_DEFAULT,
# heartbeat=_DEFAULT,
# ssl_options=_DEFAULT,
# connection_attempts=_DEFAULT,
# retry_delay=_DEFAULT,
# socket_timeout=_DEFAULT,
# stack_timeout=_DEFAULT,
# locale=_DEFAULT,
# blocked_connection_timeout=_DEFAULT,
# client_properties=_DEFAULT,
# tcp_options=_DEFAULT,
)
connection = BlockingConnection(parameters=parameters)
channel = connection.channel()
channel.queue_declare(queue='hello')
channel.basic_publish(exchange='',
routing_key='hello',
body='Hello World!')
print('已发送: Hello World!')
connection.close()
receive.py
from pika import BlockingConnection, ConnectionParameters
# RabbitMQ连接参数,基本有默认值
parameters = ConnectionParameters(
host='localhost',
# port=_DEFAULT,
# virtual_host=_DEFAULT,
# credentials=_DEFAULT,
# channel_max=_DEFAULT,
# frame_max=_DEFAULT,
# heartbeat=_DEFAULT,
# ssl_options=_DEFAULT,
# connection_attempts=_DEFAULT,
# retry_delay=_DEFAULT,
# socket_timeout=_DEFAULT,
# stack_timeout=_DEFAULT,
# locale=_DEFAULT,
# blocked_connection_timeout=_DEFAULT,
# client_properties=_DEFAULT,
# tcp_options=_DEFAULT,
)
connection = BlockingConnection(parameters=parameters)
channel = connection.channel()
channel.queue_declare(queue='hello')
def callback(ch, method, properties, body):
"""
:param ch:
:param method:
:param properties:
:param body:
:return:
"""
print("收到消息: {}".format(body))
channel.basic_consume(queue='hello',
auto_ack=True,
on_message_callback=callback)
print('等待接收消息, 按CTRL+C退出....')
channel.start_consuming()
-
先
python send.py
发送消息, 控制台输出:已发送: Hello World!
-
然后
python receive.py
, 发现控制台永远不会退出:等待接收消息, 按CTRL+C退出.... 收到消息: b'Hello World!'
-
再次
python send.py
, 会再次进行函调函数, 输出b'Hello World!'
。
原文链接。
来源:CSDN
作者:ClassmateLin
链接:https://blog.csdn.net/ClassmateLin/article/details/104575857