python队列通信:rabbitMQ的使用(实例讲解)


Posted in Python onDecember 22, 2017

(一)、前言

为什么引入消息队列?

1.程序解耦

2.提升性能

3.降低多业务逻辑复杂度

(二)、python操作rabbit mq

rabbitmq配置安装基本使用参见上节文章,不再复述。

若想使用python操作rabbitmq,需安装pika模块,直接pip安装:

pip install pika

1.最简单的rabbitmq producer端与consumer端对话:

producer:

#Author :ywq
import pika
auth=pika.PlainCredentials('ywq','qwe') #save auth indo
connection = pika.BlockingConnection(pika.ConnectionParameters(
  '192.168.0.158',5672,'/',auth)) #connect to rabbit
channel = connection.channel() #create channel
channel.queue_declare(queue='hello') #declare queue
#n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
channel.basic_publish(exchange='',
   routing_key='hello',
   body='Hello World!') #the body is the msg content
print(" [x] Sent 'Hello World!'")
connection.close()

consumer:

#Author :ywq
import pika
auth=pika.PlainCredentials('ywq','qwe') #auth info
connection = pika.BlockingConnection(pika.ConnectionParameters(
  '192.168.0.158',5672,'/',auth)) #connect to rabbit
channel = connection.channel()  #create channel

channel.queue_declare(queue='hello') #decalre queue
def callback(ch, method, properties, body):
 print(" [x] Received %r" % body)

channel.basic_consume(callback,
   queue='hello',
   no_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

消息传递消费过程中,可以在rabbit web管理页面实时查看队列消息信息。

python队列通信:rabbitMQ的使用(实例讲解)

2.持久化的消息队列,避免宕机等意外情况造成消息队列丢失。

consumer端无需改变,在producer端代码内加上两个属性,分别使消息持久化、队列持久化,只选其一还是会出现消息丢失,必须同时开启:

delivery_mode=2 #make msg persisdent
durable=True

属性插入位置见如下代码(producer端):

#Author :ywq
import pika,sys
auth_info=pika.PlainCredentials('ywq','qwe')
connection=pika.BlockingConnection(pika.ConnectionParameters(
  '192.168.0.158',5672,'/',auth_info
 ))
channel=connection.channel()
channel.queue_declare(queue='test1',durable=True) #durable=Ture, make queue persistent

msg=''.join(sys.argv[1:]) or 'Hello'
channel.basic_publish(
 exchange='',
 routing_key='test1',
 body=msg,
 properties=pika.BasicProperties(
  delivery_mode=2 #make msg persisdent
 )
)

print('Send done:',msg)
connection.close()

3.公平分发

在多consumer的情况下,默认rabbit是轮询发送消息的,但有的consumer消费速度快,有的消费速度慢,为了资源使用更平衡,引入ack确认机制。consumer消费完消息后会给rabbit发送ack,一旦未ack的消息数量超过指定允许的数量,则不再往该consumer发送,改为发送给其他consumer。

producer端代码不用改变,需要给consumer端代码插入两个属性:

channel.basic_qos(prefetch_count= *) #define the max non_ack_count
channel.basic_ack(delivery_tag=deliver.delivery_tag) #send ack to rabbitmq

属性插入位置见如下代码(consumer端):

#Author :ywq
import pika,time
auth_info=pika.PlainCredentials('ywq','qwe')
connection=pika.BlockingConnection(pika.ConnectionParameters(
 '192.168.0.158',5672,'/',auth_info
 )
)
channel=connection.channel()
channel.queue_declare(queue='test2',durable=True)
def callback(chann,deliver,properties,body):
 print('Recv:',body)
 time.sleep(5)
 chann.basic_ack(delivery_tag=deliver.delivery_tag) #send ack to rabbit
channel.basic_qos(prefetch_count=1)
'''
注意,no_ack=False 注意,这里的no_ack类型仅仅是告诉rabbit该消费者队列是否返回ack,若要返回ack,需要在callback内定义
prefetch_count=1,未ack的msg数量超过1个,则此consumer不再接受msg,此配置需写在channel.basic_consume上方,否则会造成non_ack情况出现。
'''
channel.basic_consume(
 callback,
 queue='test2'
)

channel.start_consuming()

三、消息发布/订阅

上方的几种模式都是producer端发送一次,则consumer端接收一次,能不能实现一个producer发送,多个关联的consumer同时接收呢?of course,rabbit支持消息发布订阅,共支持三种模式,通过组件exchange转发器,实现3种模式:

python队列通信:rabbitMQ的使用(实例讲解)

fanout: 所有bind到此exchange的queue都可以接收消息,类似广播。

direct: 通过routingKey和exchange决定的哪个唯一的queue可以接收消息,推送给绑定了该queue的consumer,类似组播。

topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息,类似前缀列表匹配路由。

1.fanout

publish端(producer):

#Author :ywq
import pika,sys,time
auth_info=pika.PlainCredentials('ywq','qwe')
connection=pika.BlockingConnection(pika.ConnectionParameters(
 '192.168.0.158',5672,'/',auth_info
 )
)
channel=connection.channel()
channel.exchange_declare(exchange='hello',
    exchange_type='fanout'
    )
msg=''.join(sys.argv[1:]) or 'Hello world %s' %time.time()
channel.basic_publish(
 exchange='hello',
 routing_key='',
 body=msg,
 properties=pika.BasicProperties(
 delivery_mode=2
 )
)
print('send done')
connection.close()

subscribe端(consumer):

#Author :ywq
import pika
auth_info=pika.PlainCredentials('ywq','qwe')
connection=pika.BlockingConnection(pika.ConnectionParameters(
 '192.168.0.158',5672,'/',auth_info
 )
)
channel=connection.channel()
channel.exchange_declare(
 exchange='hello',
 exchange_type='fanout'
)
random_num=channel.queue_declare(exclusive=True) #随机与rabbit建立一个queue,comsumer断开后,该queue立即删除释放
queue_name=random_num.method.queue
channel.basic_qos(prefetch_count=1)
channel.queue_bind(
 queue=queue_name,
 exchange='hello'
)
def callback(chann,deliver,properties,body):
 print('Recv:',body)
 chann.basic_ack(delivery_tag=deliver.delivery_tag) #send ack to rabbit

channel.basic_consume(
 callback,
 queue=queue_name,
)
channel.start_consuming()

实现producer一次发送,多个关联consumer接收。

使用exchange模式时:

1.producer端不再申明queue,直接申明exchange

2.consumer端仍需绑定队列并指定exchange来接收message

3.consumer最好创建随机queue,使用完后立即释放。

随机队列名在web下可以检测到:

python队列通信:rabbitMQ的使用(实例讲解)

2.direct

python队列通信:rabbitMQ的使用(实例讲解)

使用exchange同时consumer有选择性的接收消息。队列绑定关键字,producer将数据根据关键字发送到消息exchange,exchange根据 关键字 判定应该将数据发送至指定队列,consumer相应接收。即在fanout基础上增加了routing key.

producer:

#Author :ywq
import pika,sys
auth_info=pika.PlainCredentials('ywq','qwe')
connection=pika.BlockingConnection(pika.ConnectionParameters(
 '192.168.0.158',5672,'/',auth_info
 )
)
channel=connection.channel()
channel.exchange_declare(exchange='direct_log',
   exchange_type='direct',
   )
while True:
 route_key=input('Input routing key:')
 msg=''.join(sys.argv[1:]) or 'Hello'
 channel.basic_publish(
 exchange='direct_log',
 routing_key=route_key,
 body=msg,
 properties=pika.BasicProperties(
  delivery_mode=2
 )
 )
connection.close()

consumer:

#Author :ywq
import pika,sys
auth_info=pika.PlainCredentials('ywq','qwe')
connection=pika.BlockingConnection(pika.ConnectionParameters(
 '192.168.0.158',5672,'/',auth_info
))
channel=connection.channel()
channel.exchange_declare(
 exchange='direct_log',
 exchange_type='direct'
)
queue_num=channel.queue_declare(exclusive=True)
queue_name=queue_num.method.queue
route_key=input('Input routing key:')

channel.queue_bind(
 queue=queue_name,
 exchange='direct_log',
 routing_key=route_key
)
def callback(chann,deliver,property,body):
 print('Recv:[level:%s],[msg:%s]' %(route_key,body))
 chann.basic_ack(delivery_tag=deliver.delivery_tag)

channel.basic_qos(prefetch_count=1)
channel.basic_consume(
 callback,
 queue=queue_name
)
channel.start_consuming()

同时开启多个consumer,其中两个接收notice,两个接收warning,运行效果如下:

python队列通信:rabbitMQ的使用(实例讲解)

3.topic

python队列通信:rabbitMQ的使用(实例讲解)

相较于direct,topic能实现模糊匹配式工作方式(在consumer端指定匹配方式),只要routing key包含指定的关键字,则将该msg发往绑定的queue上。

rabbitmq通配符规则:

符号“#”匹配一个或多个词,符号“”匹配一个词。因此“abc.#”能够匹配到“abc.m.n”,但是“abc.*‘' 只会匹配到“abc.m”。‘.'号为分割符。使用通配符匹配时必须使用‘.'号分割。

producer:

#Author :ywq
import pika,sys
auth_info=pika.PlainCredentials('ywq','qwe')
connection=pika.BlockingConnection(pika.ConnectionParameters(
 '192.168.0.158',5672,'/',auth_info
 )
)
channel=connection.channel()
channel.exchange_declare(exchange='topic_log',
   exchange_type='topic',
   )
while True:
 route_key=input('Input routing key:')
 msg=''.join(sys.argv[1:]) or 'Hello'
 channel.basic_publish(
 exchange='topic_log',
 routing_key=route_key,
 body=msg,
 properties=pika.BasicProperties(
  delivery_mode=2
 )
 )
connection.close()

consumer:

#Author :ywq
import pika,sys
auth_info=pika.PlainCredentials('ywq','qwe')
connection=pika.BlockingConnection(pika.ConnectionParameters(
 '192.168.0.158',5672,'/',auth_info
))
channel=connection.channel()
channel.exchange_declare(
 exchange='topic_log',
 exchange_type='topic'
)
queue_num=channel.queue_declare(exclusive=True)
queue_name=queue_num.method.queue
route_key=input('Input routing key:')

channel.queue_bind(
 queue=queue_name,
 exchange='topic_log',
 routing_key=route_key
)
def callback(chann,deliver,property,body):
 print('Recv:[type:%s],[msg:%s]' %(route_key,body))
 chann.basic_ack(delivery_tag=deliver.delivery_tag)

channel.basic_qos(prefetch_count=1)
channel.basic_consume(
 callback,
 queue=queue_name
)
channel.start_consuming()

运行效果:

python队列通信:rabbitMQ的使用(实例讲解)

rabbitmq三种publish/subscribe模型简单介绍完毕。

以上这篇python队列通信:rabbitMQ的使用(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python MD5文件生成码
Jan 12 Python
Python实现设置windows桌面壁纸代码分享
Mar 28 Python
Python实现的使用telnet登陆聊天室实例
Jun 17 Python
Python hashlib模块用法实例分析
Jun 12 Python
python绘制多个曲线的折线图
Mar 23 Python
Python中修改字符串的四种方法
Nov 02 Python
Pycharm保存不能自动同步到远程服务器的解决方法
Jun 27 Python
Python跳出多重循环的方法示例
Jul 03 Python
django rest framework 实现用户登录认证详解
Jul 29 Python
对python中的装包与解包实例详解
Aug 24 Python
python3实现elasticsearch批量更新数据
Dec 03 Python
tensorflow实现测试时读取任意指定的check point的网络参数
Jan 21 Python
python3写爬取B站视频弹幕功能
Dec 22 #Python
机器学习经典算法-logistic回归代码详解
Dec 22 #Python
利用python将xml文件解析成html文件的实现方法
Dec 22 #Python
python实现数据预处理之填充缺失值的示例
Dec 22 #Python
NetworkX之Prim算法(实例讲解)
Dec 22 #Python
Python实现控制台中的进度条功能代码
Dec 22 #Python
Python中的探索性数据分析(功能式)
Dec 22 #Python
You might like
php中时间轴开发(刚刚、5分钟前、昨天10:23等)
2011/10/03 PHP
PHP中3种生成XML文件方法的速度效率比较
2012/10/06 PHP
php预定义变量使用帮助(带实例)
2013/10/30 PHP
基于PHP+mysql实现新闻发布系统的开发
2020/08/06 PHP
网页图片延时加载的js代码
2010/04/22 Javascript
跨域请求之jQuery的ajax jsonp的使用解惑
2011/10/09 Javascript
javascript中onclick(this)用法介绍
2013/04/19 Javascript
公共js在页面底部加载的注意事项介绍
2013/07/18 Javascript
js获取窗口相对于屏幕左边和上边的位置坐标
2014/05/15 Javascript
深入理解JavaScript系列(41):设计模式之模板方法详解
2015/03/04 Javascript
jquery实现的伪分页效果代码
2015/10/29 Javascript
Vue.js快速入门教程
2016/09/07 Javascript
angularjs实现过滤并替换关键字小功能
2017/09/19 Javascript
让bootstrap的carousel支持滑动滚屏的实现代码
2017/11/27 Javascript
Vue 应用中结合vux使用微信 jssdk的方法
2018/08/28 Javascript
如何解决.vue文件url引用文件的问题
2019/01/18 Javascript
jquery分页优化操作实例分析
2019/08/23 jQuery
vue+Element中table表格实现可编辑(select下拉框)
2020/05/21 Javascript
Python 字符串大小写转换的简单实例
2017/01/21 Python
在python win系统下 打开TXT文件的实例
2018/04/29 Python
Python实现KNN(K-近邻)算法的示例代码
2019/03/05 Python
python中的列表与元组的使用
2019/08/08 Python
利用rest framework搭建Django API过程解析
2019/08/31 Python
简单了解python filter、map、reduce的区别
2020/01/14 Python
地图可视化神器kepler.gl python接口的使用方法
2020/12/22 Python
css3新增颜色表示方式分享
2014/04/15 HTML / CSS
纯css3实现鼠标经过图片显示描述的动画效果
2014/09/01 HTML / CSS
Sneaker Studio匈牙利:购买运动鞋
2018/03/26 全球购物
总经理秘书工作职责
2013/12/26 职场文书
中式面点餐厅创业计划书
2014/01/29 职场文书
《鸟的天堂》教学反思
2014/02/27 职场文书
五年级学生评语
2014/04/22 职场文书
2015年幼儿园元旦游艺活动策划书
2014/12/09 职场文书
乌镇导游词
2015/02/02 职场文书
中学综治宣传月活动总结
2015/05/07 职场文书
幼儿教师师德培训心得体会
2016/01/09 职场文书