python学习之路-RabbitMQ-day11

来源:互联网 发布:淘宝免费送衣服是真的 编辑:程序博客网 时间:2024/06/13 23:03

大纲:
1.RabbitMQ概述
2.创建简单的RabbitMQ
3.消息分发轮询
4.消息持久化
5.消息发布和订阅
6.有选择的接收消息
7.更细致的过滤消息
8.RPC
一.RabbitMQ概述
RabbitMQ就是消息队列
Python已经有了Queue队列了,为什么还需要RabbitMQ?
Queue只能是python内部使用,分为线程队列和进程队列:
线程队列用于多个线程间的数据交换
进程队列用于父进程和子进程,或者同属于一个父进程下的多个子进程之间的数据交换
如果两个独立的程序,哪怕是python程序,还有PY和PHP,Java等其他语言进行数据交换的时候Queue就不能够实现啦,这就类似于pickle和json,这个时候就需要有一个中间期间来连接两个独立的程序。这个中间期间有很多ribbitmq,zeromq,activemq等等。这里我们讲述RabbitMQ
RabbitMQ:erlang语言开发的
RabbitMQ是需要安装的,之前有介绍过win下python模块的安装方法了,这个也是一样的还是通过pycharm安装,这里就不赘述了
Python中连接RabbitMQ的模块:pika 、Celery(分布式任务队列) 、haigha
可以维护很多的队列
二.创建简单的RabbitMQ
生产端

import pikaconnection=pika.BlockingConnection(pika.ConnectionParameters("localhost"))#创建一个socketchanel=connection.channel()#声明一个管道chanel.queue_declare(queue="say")#在管道里面声明一个queuechanel.basic_publish(exchange="",#使我们能够确切地指定消息应该到哪个队列去                     routing_key="say",#队列名称                     body="how are you")#队列内容print("Start")connection.close()

消费端

import pikaconnection=pika.BlockingConnection(pika.ConnectionParameters("localhost"))#创建一个socketchanel=connection.channel()#声明一个管道chanel.queue_declare(queue="say")#在管道里面声明一个queue,因为并不知道哪个会先运行def callback(ch,method,properties,body):    print(ch,method,properties,body)#ch管道内存对象地址    print("start recve %s"%body)    ch.basic_ack(delivery_tag = method.delivery_tag)#告诉生产者消息处理完成chanel.basic_consume(#消费消息                     callback,#如果收到消息,就调用callback函数来处理消息                     queue="say",# 你要从哪个队列里收消息                     #no_ack=True#一般不谢,写的话只要死机,消息丢失                       )print("wait for message")chanel.start_consuming()#一起动就一直运行,开始消费消息#开始接收信息,并进入阻塞状态,队列里有信息才会调用callback进行处理。按ctrl+c退出

三.消息分发轮询
按照处理能力大小分配消息
消费端在chanel.basic_consume之前加上

channel.basic_qos(prefetch_count=1)

四.消息持久化
即使出现重启,消息也不会丢失
只需要修改发送端,客户端不变

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters(               'localhost'))channel = connection.channel()channel.queue_declare(queue='hello', durable=True)  # 若声明过,必须换一个名字channel.basic_publish(exchange='',                      routing_key='hello',                      body='how are you,OK?',                      properties=pika.BasicProperties(                         delivery_mode=2,#消息持久化,在投递时指定delivery_mode=> 2(1是非持久化)                      )                      )print(" start")connection.close()

五.RabbitMQ-fanout(广播)
以上都是一对一发送和接收消息,那么怎么实现一对多(生产者发送一条消息,所有的消费者都要收到)呢?
发布端

import pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()# 这里是广播,不需要声明queuechannel.exchange_declare(exchange='logs',  # 声明广播管道                         type='fanout')message = "Hello World!"channel.basic_publish(exchange='logs',                      routing_key='', #模式不需要routing_key(即使指#定,也是无效的),但必须写                       body=message)print(" [x] Sent %r" % message)connection.close()

订阅端

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='logs',                         type='fanout')# 不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除result = channel.queue_declare(exclusive=True)queue_name = result.method.queue# 获取随机的queue名字print("random queuename:", queue_name)channel.queue_bind(exchange='logs',  # queue绑定到转发器上                   queue=queue_name)print(' [*] Waiting for logs. To exit press CTRL+C')def callback(ch, method, properties, body):    print(" [x] %r" % body)channel.basic_consume(callback,                      queue=queue_name,                      no_ack=True)channel.start_consuming()

注意:这个时候必须先启即订阅者。因为随机队列是在consumer启动的时候随机生成的,并且进行绑定的。producer仅仅是发送至exchange,并不直接与随机队列进行通信。
六.有选择的接收消息-direct
七.更细致的过滤-topic
八.RabbitMQ RPC 实现

原创粉丝点击