利用Python操作消息队列RabbitMQ的方法教程


Posted in Python onJuly 19, 2017

前言

RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。
MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

应用场景:

RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具。消息队列的使用场景大概有3种:

     1、系统集成,分布式系统的设计。各种子系统通过消息来对接,这种解决方案也逐步发展成一种架构风格,即“通过消息传递的架构”。

     2、当系统中的同步处理方式严重影响了吞吐量,比如日志记录。假如需要记录系统中所有的用户行为日志,如果通过同步的方式记录日志势必会影响系统的响应速度,当我们将日志消息发送到消息队列,记录日志的子系统就会通过异步的方式去消费日志消息。

     3、系统的高可用性,比如电商的秒杀场景。当某一时刻应用服务器或数据库服务器收到大量请求,将会出现系统宕机。如果能够将请求转发到消息队列,再由服务器去消费这些消息将会使得请求变得平稳,提高系统的可用性。

一、安装环境

首先是在 Linux 上安装 rabbitmq

# 环境为CentOS 7
yum install rabbitmq-server # 安装RabbitMQ
systemctl start rabbitmq-server # 启动
systemctl enable rabbitmq-server # 开机自启
systemctl stop firewall-cmd  # 临时关闭防火墙

然后用 pip 安装 Python3 的开发包

pip3 install pika

安装好软件之后可以访问http://115.xx.xx.xx:15672/来访问自带的 web 页面来查看和管理 RabbitMQ。默认管理员的用户密码都是guest

二、简单的向队列中加入消息

#!/usr/bin/env python3
# coding=utf-8
# @Time : 2017/6/13 19:25
# @Author : Shawn
# @Blog : https://blog.just666.cn
# @Email : shawnbluce@gmail.com
# @purpose : RabbitMQ_Producer
import pika
# 创建连接对象
connection = pika.BlockingConnection(pika.ConnectionParameters(host='115.xx.xx.xx'))
# 创建频道对象
channel = connection.channel()
# 指定一个队列,如果该队列不存在则创建
channel.queue_declare(queue='test_queue')
# 提交消息
for i in range(10):
 channel.basic_publish(exchange='', routing_key='test_queue', body='hello,world' + str(i))
 print("sent...")
# 关闭连接
connection.close()

三、简单的从队列中获取消息

#!/usr/bin/env python3
# coding=utf-8
# @Time : 2017/6/13 19:40
# @Author : Shawn
# @Blog : https://blog.just666.cn
# @Email : shawnbluce@gmail.com
# @purpose : RabbitMQ_Consumer
import pika
credentials = pika.PlainCredentials('guest', 'guest')
# 连接到RabbitMQ服务器
connection = pika.BlockingConnection(pika.ConnectionParameters('115.xx.xx.xx', 5672, '/', credentials))
channel = connection.channel()
# 指定一个队列,如果该队列不存在则创建
channel.queue_declare(queue='test_queue')
# 定义一个回调函数
def callback(ch, method, properties, body):
 print(body.decode('utf-8'))
# 告诉RabbitMQ使用callback来接收信息
channel.basic_consume(callback, queue='test_queue', no_ack=False)
print('waiting...')
# 开始接收信息,并进入阻塞状态,队列里有信息才会调用callback进行处理。按ctrl+c退出。
channel.start_consuming()

四、万一消费者掉线了

想象这样一种情况:

消费者从消息队列中获取了 n 条数据,正要处理呢结果宕机了,那该怎么办?在 RabbieMQ 中有一个 ACK 可以用来确认消费者处理结束。就有点类似网络中的 ACK,消费者每次从队列中获取了数据之后队列不会立刻将数据移除,而是等待对应的 ACK。消费者获取到数据并处理完成之后会向队列发送一个 ACK 包,通知 RabbitMQ 这堆消息已经处理妥当了,可以删除了,这时候 RabbitMQ 才会将数据从队列中移除。所以这种情况下即使消费者掉线也没有什么问题,数据依旧会在队列中存在,留给其他消费者处理。

在 Python 中这样实现:

消费者有这样一行代码channel.basic_consume(callback, queue='test_queue', no_ack=False) ,其中no_ack=False表示不发送确认包。将其修改为no_ack=True就会在每次处理完之后向 RabbitMQ 发送一个确认包,以确认消息处理完毕。

五、万一 RabbitMQ 宕机了呢

虽然有了 ACK 包,但是万一 RabbitMQ 挂了那数据还是会损失。所以我们可以给 RabbitMQ 设置一个数据持久化存储。RabbitMQ 会将数据持久化存储到磁盘上,保证下次再启动的时候队列还在。

在 Python 中这样实现:

我们声明一个队列是这样的channel.queue_declare(queue='test_queue') ,如果需要持久化一个队列可以这样声明channel.queue_declare(queue='test_queue', durable=True) 。不过这行直接放在代码中是不能执行的,因为以前已经有了一个名为test_queue的队列,RabbitMQ 不允许用不同的方式声明同一个队列,所以可以换一个队列名新建来指定数据持久化存储。不过如果只是这样声明的话,在 RabbitMQ 宕机重启后确实队列还在,不过队列里的数据就没有了。除非我们这样来声明队列channel.basic_publish(exchange='', routing_key="test_queue", body=message, properties=pika.BasicProperties(delivery_mode = 2,))

六、最简单的发布订阅

最简单的发布订阅在 RabbitMQ 中称之为Fanout模式。也就是说订阅者订阅某个频道,然后发布者向这个频道中发布消息,所有订阅者就都能接收到这条消息。不过因为发布者需要使用订阅者创建的随机队列所以需要先启动订阅者才能启动发布者。

发布者代码:

#!/usr/bin/env python3
# coding=utf-8
# @Time : 2017/6/13 20:21
# @Author : Shawn
# @Blog : https://blog.just666.cn
# @Email : shawnbluce@gmail.com
# @purpose : RabbitMQ_Publisher
import pika
# 创建连接对象
connection = pika.BlockingConnection(pika.ConnectionParameters(host='115.xx.xx.xx'))
# 创建频道对象
channel = connection.channel()
# 定义交换机,exchange表示交换机名称,type表示类型
channel.exchange_declare(exchange='my_fanout',
       type='fanout')
message = 'Hello Python'
# 将消息发送到交换机
channel.basic_publish(exchange='my_fanout', # 指定exchange
      routing_key='', # fanout下不需要配置,配置了也不会生效
      body=message)
connection.close()

订阅者代码:

#!/usr/bin/env python3
# coding=utf-8
# @Time : 2017/6/13 20:20
# @Author : Shawn
# @Blog : https://blog.just666.cn
# @Email : shawnbluce@gmail.com
# @purpose : RabbitMQ_Subscriber
import pika
credentials = pika.PlainCredentials('guest', 'guest')
# 连接到RabbitMQ
connection = pika.BlockingConnection(pika.ConnectionParameters('115.xx.xx.xx', 5672, '/', credentials))
channel = connection.channel()
# 定义交换机,进行exchange声明,exchange表示交换机名称,type表示类型
channel.exchange_declare(exchange='my_fanout',
       type='fanout')
# 随机创建队列
result = channel.queue_declare(exclusive=True) # exclusive=True表示建立临时队列,当consumer关闭后,该队列就会被删除
queue_name = result.method.queue
# 将队列与exchange进行绑定
channel.queue_bind(exchange='my_fanout',
     queue=queue_name)
# 定义回调方法
def callback(ch, method, properties, body):
 print(body.decode('utf-8'))
# 从队列获取信息
channel.basic_consume(callback,
      queue=queue_name,
      no_ack=True)
channel.start_consuming()

总结

以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python中使用异常处理来判断运行的操作系统平台方法
Jan 22 Python
进一步了解Python中的XML 工具
Apr 13 Python
python从入门到精通(DAY 1)
Dec 20 Python
初探TensorFLow从文件读取图片的四种方式
Feb 06 Python
python如何在循环引用中管理内存
Mar 20 Python
python抓取网站的图片并下载到本地的方法
May 22 Python
python 删除字符串中连续多个空格并保留一个的方法
Dec 22 Python
Python any()函数的使用方法
Oct 28 Python
详解Django配置优化方法
Nov 18 Python
python中JWT用户认证的实现
May 18 Python
Python3爬虫里关于代理的设置总结
Jul 30 Python
python利用xlsxwriter模块 操作 Excel
Oct 14 Python
高效测试用例组织算法pairwise之Python实现方法
Jul 19 #Python
Python实现将文本生成二维码的方法示例
Jul 18 #Python
Python实现动态加载模块、类、函数的方法分析
Jul 18 #Python
Python使用plotly绘制数据图表的方法
Jul 18 #Python
python中日志logging模块的性能及多进程详解
Jul 18 #Python
浅谈python中的__init__、__new__和__call__方法
Jul 18 #Python
Pycharm编辑器技巧之自动导入模块详解
Jul 18 #Python
You might like
一个程序下载的管理程序(二)
2006/10/09 PHP
深入PHP中的HashTable结构详解
2013/06/13 PHP
php获取网页里所有图片并存入数组的方法
2015/04/06 PHP
PHP实现获取文件后缀名的几种常用方法
2015/08/08 PHP
PHP中使用foreach()遍历二维数组的简单实例
2016/06/13 PHP
Laravel 模型关联基础教程详解
2019/09/17 PHP
javascript 带有滚动条的表格,标题固定,带排序功能.
2009/11/13 Javascript
js实现翻页后保持checkbox选中状态的实现方法
2012/11/03 Javascript
JS中for循序中延迟加载动态效果的具体实现
2013/08/18 Javascript
table insertRow、deleteRow定义和用法总结
2014/05/14 Javascript
JavaScript sub方法入门实例(把字符串显示为下标)
2014/10/17 Javascript
修改js confirm alert 提示框文字的简单实例
2016/06/10 Javascript
ES6中Math对象新增的方法实例详解
2017/04/25 Javascript
微信小程序实现城市列表选择
2018/06/05 Javascript
JQuery获取可视区尺寸和文档尺寸及制作悬浮菜单示例
2019/05/14 jQuery
websocket4.0+typescript 实现热更新的方法
2019/08/14 Javascript
Element Badge标记的使用方法
2020/07/27 Javascript
[06:33]DOTA2亚洲邀请赛小组赛第二日 TOP10精彩集锦
2015/01/31 DOTA
python实现socket客户端和服务端简单示例
2014/02/24 Python
python实现下载整个ftp目录的方法
2017/01/17 Python
python opencv 读取图片 返回图片某像素点的b,g,r值的实现方法
2019/07/03 Python
django queryset 去重 .distinct()说明
2020/05/19 Python
python退出循环的方法
2020/06/18 Python
matplotlib运行时配置(Runtime Configuration,rc)参数rcParams解析
2021/01/05 Python
英国演唱会订票网站:Ticket Selection
2018/03/27 全球购物
Lyle & Scott苏格兰金鹰官网:英国皇室御用品牌
2018/05/09 全球购物
大学生实习自我鉴定
2013/12/11 职场文书
还款承诺书范文
2014/05/20 职场文书
淘宝客服工作职责
2014/07/11 职场文书
科长个人四风问题整改措施思想汇报
2014/10/13 职场文书
企业年检委托书范本
2014/10/14 职场文书
亮剑观后感
2015/06/05 职场文书
我的生日感言
2015/08/03 职场文书
体育教师教学随笔
2015/08/15 职场文书
六年级数学教学反思
2016/02/16 职场文书
关于JavaScript回调函数的深入理解
2021/06/27 Javascript