今天总结一下Python关于Rabbitmq的使用
RabbitMQ官网说明,其实也是一种队列,那和前面说的线程queue和进程queue有什么区别呢?
线程queue只能在同一个进程下进行数据交互
进程queue只能在父进程和子进程之间,或者同一父进程下的子进程之间做数据交互
如果需要对不同进程(eg:微信和qq)两个独立的程序间通信
方法1就是直接把数据写在硬盘(disk)上然后各自的进程读取数据就可以,但是由于硬盘的读写速度太慢,效率太低
方法2自己写个socket,直接做数据交互,问题是如果改变程序,或者再加一个程序,需要对写好的socket进行修改,还要处理黏包什么的复杂的连接关系,维护成本太高。
方法3,利用已有的中间商(代理)。这个broker其实就是封装好的socket,我们拿来直接用就好了。
这里的broker,就有RabbitMQ,ZeroMQ,ActiveMQ等等等等。
一.安装及环境配置
windows的安装和配置方法较为简单,直接安装就好了
Rabbit支持多种语言: Java, .NET, PHP, Python, JavaScript, Ruby, Go这些常用语言都支持
如图所示,python操作RabbitMQ需要的模块有上述几种选择,我们用最简单的pika,用pip直接安装
pip install pika
二.RabbitMQ的使用
这里所有的用法都是基于RabbitMQ是工作在‘localhost’上,并且端口号为15672,能在浏览器里访问http://localhost:15672这个地址。
1.最基础的用法
这就是RabbitMQ最简单的工作模式,p为生产者(Producer),生产者发送message给queue,queue再把消息发送至消费者c(Customer)
先看看生产者至队列(send)这个过程
import pika
connect = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connect.channel()
我们先建立了一个链接,然后就需要定义一个队列,队列的名字就暂时定位‘hello'
channel.queue_declare(queue='hello')
在RabbitMQ里消息并不能直接发送给队列,所有的信息发送都要通过一个exchange,但是这里我们先把这个exchange定义成一个空的字符串,后面在将他的具体用法
channel.basic_publish(exchange='',
routing_key='hello',
body='123')
在发送确认完成后,可以将连接关闭
connect.close()
这就是send端的代码
import pika connect = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connect.channel() channel.queue_declare(queue='hello') channel.basic_publish(exchange='', routing_key='hello', body='123') print("[x] Sent 'hello world!'") connect.close()
运行了send代码后我们可以在terminal里RabbitMQ安装目录下sbin文件夹里查看一下消息队列
rabbitmqctl.bat list_queues
如果是Linux命令为
sudo rabbitmqctl list_queues
这里就说明了队列信息和消息状态。
然后再看一下消费者这一端的代码是什么样的,同样,先要建立连接并定义好队列名
connect = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connect.channel()
channel.queue_declare(queue='hello')
这里可能有个疑问:我们不是在生产者里已经定义了队列名吗?为什么在消费者里还要定义呢?
因为在实际工作中,我们并不能确定是生产者还是消费者先一步运行,如果队列名没有定义的话运行时候是会报错的。下面就是对消息的处理
def callback(ch,method,properties,body):
print("[x] Received %r"%body)
channel.basic_consume(callback,
queue='hello',
no_ack=True)
当消息来临时,消费者会执行回调函数callback。这里的callback就是直接打印消息内容(body)。
回调函数另外的几个参数:ch是conne.channel的内存对象地址,
<BlockingChannel impl=<Channel number=1 OPEN conn=<SelectConnection OPEN socket=('::1', 62145, 0, 0)->('::1', 5672, 0, 0) params=<ConnectionParameters host=localhost port=5672 virtual_host=/ ssl=False>>>>
method是包含了发送的信息
<Basic.Deliver(['consumer_tag=ctag1.9ae48c906b014a83a512413c0e6f9ef8', 'delivery_tag=1', 'exchange=', 'redelivered=False', 'routing_key=hello'])>
properties我们以后再了解