RabbitMQ应用实例Python版-Hello World
原文:http://www.ywnds.com/?p=5306
介绍 RabbitMQ是一个消息代理。它的核心原理非常简单:接收和发送消息.
RabbitMQ用到一些专有名词
生产(Producing) 意思就是发送。发送消息的程序就是一个生产者(producer)。我们一般用”P”来表示。
队列(queue) 消息通过你的应用程序和RabbitMQ进行传输,它们能够只存储在一个队列(queue)中。 队列(queue)没有任何限制,你要存储多少消息都可以——基本上是一个无限的缓冲。多个生产者(producers)能够把消息发送给同一个队列,同样,多个消费者(consumers)也能够从同一个队列(queue)中获取数据。
消费(Consuming) 和获取消息是一样的意思。一个消费者(consumer)就是一个等待获取消息的程序。
需要指出的是生产者、消费者、代理不需要在同一个设备上;事实上大多数应用也确实不在会将他们放在一台机器上。
Hello World!
我们将会设计两个程序,一个发送Hello world,另一个接收这个数据并且打印到屏幕。 本文将使用Python(pika 0.9.8)实现从Producer到Consumer传递数据”Hello, World”,如果使用pipa最新版需要python3的支持。
复习一下:RabbitMQ实现了AMQP定义的消息队列。它实现的功能”非常简单“:从Producer接收数据然后传递到Consumer。 它能保证多并发,数据安全传递,可扩展。和任何的Hello world一样,它们都不复杂。
RabbitMQ库
RabbitMQ使用的是AMQP协议。要使用她你就必须需要一个使用同样协议的库。java、python等编程语言都有可选择的库。Python可以从以下几个库中选择:
py-amqplib
txAMQP
pika
在这一系列教程中,我们打算使用pika。要安装pika,可以python的pip包管理工具:
pip install pika==0.9.8
安装过程依赖于pip和git-core两个包,你需要先安装它们。
yum install -y python-pip git-core
发送消息
我们第一个程序send.py会发送一个消息到队列中。首先要做的事情就是建立一个到RabbitMQ服务器的连接, 设置用户名和密码,然后设置RabbitMQ的连接服务器,端口以及。
#!/usr/bin/env python import pika credentials = pika.PlainCredentials('guest','123456') connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials)) channel = connection.channel() #根据类创建出channel的实例,创建实例是通过类名+()实现的
现在我们已经连接上服务器了,那么,在发送消息之前我们需要确认队列是存在的。如果我们把消息发送到一个不存在的队列, RabbitMQ会丢弃这条消息。我门先创建一个名为hello的队列,然后把消息发送到这个队列中。
channel.queue_declare(queue='hello')
在RabbitMQ中,消息是不能直接发送到队列,它需要发送到交换机(exchange)中。不打算在这里深入讨论它——你可以通过后面的部分了解更多。 现在我们所需要了解的是如何使用默认的交换机(exchange),它使用一个空字符串来标识。交换机允许我们指定某条消息需要投递到哪个队列, routing_key参数必须指定为队列的名称:
channel.basic_publish(exchange='', #默认的交换机 routing_key='hello', #队列名 body='Hello World!') #消息内容 print " [x] Sent 'Hello World!'"
在退出程序之前,我们需要确认网络缓冲已经被刷写、消息已经投递到RabbitMQ。完成这些事情(正确的关闭连接)是很简单的。
connection.close()
获取数据
我们的第二个程序receive.py,将会从队列中获取消息并打印消息。
这次我们还是先要连接到RabbitMQ服务器。连接服务器的代码和之前是一样的。 下一步也和之前一样,我们需要确认队列是存在的。使用queue_declare创建一个队列——我们可以运行这个命令很多次,但是只有一个队列会被创建。
channel.queue_declare(queue='hello')
你也许要问: 为什么要重复声明队列呢 —— 我们已经在前面的代码中声明过它了。如果我们确定了队列是已经存在的,那么我们可以不这么做, 比如此前预先运行了send.py程序。可是我们并不确定哪个程序会首先运行。这种情况下,在程序中重复将队列重复声明一下是种值得推荐的做法。
列出所有队列
你也许希望查看RabbitMQ中有哪些队列、有多少消息在队列中。此时你可以使用rabbitmqctl工具(使用有权限的用户):
# rabbitmqctl list_queues Listing queues ... 160chuan 1 jiang 0 hello 3
从队列中获取消息需要为队列定义一个回调(callback)函数。当我们获取到消息的时候,Pika库就会调用此回调函数。这个回调函数会将接收到的消息内容输出到屏幕上。
def callback(ch, method, properties, body):
print " [x] Received %r" % (body,)
下一步,我们需要告诉RabbitMQ这个回调函数将会从名为”hello”的队列中接收消息:
channel.basic_consume(callback, queue='hello', no_ack=True)
要成功运行这些命令,我们必须保证队列是存在的,我们的确可以确保它的存在——因为我们之前已经使用queue_declare将其声明过了。
最后,我们输入一个用来等待消息数据并且在需要的时候运行回调函数的无限循环。
print ' [*] Waiting for messages. To exit press CTRL+C' channel.start_consuming()
整合
send.py的全部代码:
#!/usr/bin/env python import pika credentials = pika.PlainCredentials('guest','123456') connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials)) 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的全部代码:
#!/usr/bin/env python import pika credentials = pika.PlainCredentials('guest','123456') connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials)) channel = connection.channel() channel.queue_declare(queue='hello') print ' [*] Waiting for messages. To exit press CTRL+C' def callback(ch, method, properties, body): print " [x] Received %r" % (body,) channel.basic_consume(callback, queue='hello', no_ack=True) channel.start_consuming()
执行结果
现在就可以在终端中运行我们的程序了。首先,用send.py重续发送一条消息:
[root@test161 tmp]# python send.py [x] Sent 'Hello World,This is my messages!'
生产者(producer)程序send.py每次运行之后就会停止。现在我们就来接收消息
[root@test161 tmp]# python receive.py [*] Waiting for messages. To exit press CTRL+C [x] Received 'Hello World,160chuan!' [x] Received 'wo wo zai chuan'
成功了!我们已经通过RabbitMQ发送第一条消息。你也许已经注意到了,receive.py程序并没有退出。它一直在准备获取消息,你可以通过Ctrl-C来中止它。 看RabbitMQ中有哪些队列、有多少消息在队列中

浙公网安备 33010602011771号