消息队列之rabbitmq学习使用
消息队列之rabbitmq学习使用
1、RabbitMQ简介
1.1、什么是RabbitMQ?
RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,RabbitMQ是使用Erlang语言来编写的,并且RabbitMQ是基于 AMQP协议的。
1.2、RabbitMQ有哪些特点?
目前大多数互联网都在使用RabbitMQ
RabbitMQ底层采用Erlang语言进行编写
开源、性能优秀,稳定
与SpringAMQP完美的整合、API丰富,只要是你能想到的编程语言几乎都有与其相适配的RabbitMQ客户端。
集群模式丰富,表达式配置,HA模式,镜像队列模型
保证数据不丢失的前提做到高可靠、可用性
RabbitMQ附带了一个易于使用的可视化管理工具,它可以帮助你监控消息代理的每一个环节。
如果你的消息系统有异常行为,RabbitMQ还提供了追踪的支持,让你能够发现问题所在。
RabbitMQ附带了各种各样的插件来对自己进行扩展。你甚至也可以写自己的插件来使用。
1.3、AMQP协议模型

2、RabbitMQ安装使用
2.1 安装rabbitmq,配置好阿里云的yum源,epel源
yum -y install erlang rabbitmq-server
2.2 启动rabbitmq服务端
systemctl start rabbitmq-server
2.3 创建rabbitmq的后台管理用户
- 创建用户
sudo rabbitmqctl add_user 账户 密码
[root@zfy2 ~]# rabbitmqctl add_user admin 000000
Creating user "admin" ...
...done.
- 设置用户管理员身份
sudo rabbitmqctl set_user_tags 账户 administrator
[root@zfy2 ~]# rabbitmqctl set_user_tags admin administrator
Setting tags for user "admin" to [administrator] ...
...done.
- 允许用户对所有的队列都可以读写
sudo rabbitmqctl set_permissions -p "/" xiaohu ".*" ".*" ".*"
[root@zfy2 ~]# rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
Setting permissions for user "admin" in vhost "/" ...
...done.
- 重启服务端,让用户添加生效
systemctl restart rabbitmq-server
- 开启web界面rabbitmq
rabbitmq-plugins enable rabbitmq_management
- 访问web界面默认端口的
15672
http://192.168.16.193:15672/

2.4 下面是一些关于用户操作的命令
# 新建用户
rabbitmqctl add_user {用户名} {密码}
# 设置权限
rabbitmqctl set_user_tags {用户名} {权限}
# 查看用户列表
rabbitmqctl list_users
# 为用户授权
# 添加 Virtual Hosts :
rabbitmqctl add_vhost <vhost>
# 删除用户
rabbitmqctl delete_user Username
# 修改用户的密码
rabbitmqctl change_password Username Newpassword
# 删除 Virtual Hosts :
rabbitmqctl delete_vhost <vhost>
# 添加 Users :
rabbitmqctl add_user <username> <password>
rabbitmqctl set_user_tags <username> <tag> ...
rabbitmqctl set_permissions [-p <vhost>] <user> <conf> <write> <read>
# 删除 Users :
delete_user <username>
# 使用户user1具有vhost1这个virtual host中所有资源的配置、写、读权限以便管理其中的资源
rabbitmqctl set_permissions -p vhost1 user1 '.*' '.*' '.*'
# 查看权限
rabbitmqctl list_user_permissions user1
rabbitmqctl list_permissions -p vhost1
# 清除权限
rabbitmqctl clear_permissions [-p VHostPath] User
# 清空队列步骤
rabbitmqctl reset
需要提前关闭应用 rabbitmqctl stop_app
然后再清空队列,启动应用
rabbitmqctl start_app
此时查看队列rabbitmqctl list_queues
查看所有的exchange: rabbitmqctl list_exchanges
查看所有的queue: rabbitmqctl list_queues
查看所有的用户: rabbitmqctl list_users
查看所有的绑定(exchange和queue的绑定信息): rabbitmqctl list_bindings
查看消息确认信息:
rabbitmqctl list_queues name messages_ready messages_unacknowledged
查看RabbitMQ状态,包括版本号等信息:rabbitmqctl status
2.5 安装pika模块
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple pika==0.11.1
2.6 创建一个py文件
[root@zfy2 rabbitmq]# touch send.py
[root@zfy2 rabbitmq]# touch Receive.py
2.7 通过python的pika模块,实现生产消费者
- 生产者代码如下
send.py
#!/usr/bin/env python
import pika
# 创建凭证,使用rabbitmq用户密码登录
credentials = pika.PlainCredentials("admin","000000")
# 新建连接,这里localhost可以更换为服务器ip
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.16.193',credentials=credentials))
# 创建频道
channel = connection.channel()
# 声明一个队列,用于接收消息,队列名字叫“西游记”
channel.queue_declare(queue='西游记')
# 注意在rabbitmq中,消息想要发送给队列,必须经过交换(exchange),初学可以使用空字符串交换(exchange=''),它允许我们精确的指定发送给哪个队列(routing_key=''),参数body值发送的数据
channel.basic_publish(exchange='',
routing_key='西游记',
body='大师兄,师傅被妖怪抓走了')
print("已经发送了消息")
# 程序退出前,确保刷新网络缓冲以及消息发送给rabbitmq,需要关闭本次连接
connection.close()
执行代码:
[root@zfy2 rabbitmq]# python3 send.py
已经发送了消息

- 运行消费者代码
Receive.py
import pika
# 建立与rabbitmq的连接
# 前四行都是连接到同一个rabbitmq服务端以及同一个队列
credentials = pika.PlainCredentials("admin","000000")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.16.193',credentials=credentials))
channel = connection.channel()
channel.queue_declare(queue="西游记")
def callbak(ch,method,properties,body):
print("消费者取出了消息:%r"%body.decode("utf8"))
# 有消息来临,立即执行callbak,没有消息则夯住,等待消息
channel.basic_consume(callbak,queue="西游记",no_ack=True) #no_ack 不用确认
# 开始消费,接收消息
channel.start_consuming()
执行代码:
[root@zfy2 rabbitmq]# python3 Receive.py
消费者取出了消息:'大师兄,师傅被妖怪抓走了'
2.8 消息应答之ack机制
为了确保消息不会丢失,RabbitMQ支持消息应答。消费者发送一个消息应答,告诉RabbitMQ这个消息已经接收并且处理完毕了。RabbitMQ就可以删除它了。
如果一个消费者挂掉却没有发送应答,RabbitMQ会理解为这个消息没有处理完全,然后交给另一个消费者去重新处理。这样,你就可以确认即使消费者偶尔挂掉也不会丢失任何消息了。
没有任何消息超时限制;只有当消费者挂掉时,RabbitMQ才会重新投递。即使处理一条消息会花费很长的时间。
消息应答是默认打开的。我们通过显示的设置autoAsk=true关闭这种机制。现即自动应答开,一旦我们完成任务,消费者会自动发送应答。通知RabbitMQ消息已被处理,可以从内存删除。如果消费者因宕机或链接失败等原因没有发送ACK(不同于ActiveMQ,在RabbitMQ里,消息没有过期的概念),则RabbitMQ会将消息重新发送给其他监听在队列的下一个消费者。
- 生产者代码如下
#!/usr/bin/env python
import pika
# 创建凭证,使用rabbitmq用户密码登录
credentials = pika.PlainCredentials("admin","000000")
# 新建连接,这里localhost可以更换为服务器ip
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.16.193',credentials=credentials))
# 创建频道
channel = connection.channel()
# 新建一个hello队列,用于接收消息
channel.queue_declare(queue='金品没')
# 注意在rabbitmq中,消息想要发送给队列,必须经过交换(exchange),初学可以使用空字符串交换(exchange=''),它允许我们精确的指定发送给哪个队列(routing_key=''),参数body值发送的数据
channel.basic_publish(exchange='',
routing_key='金品没',
body='大郎,起来喝药了')
print("已经发送了消息")
# 程序退出前,确保刷新网络缓冲以及消息发送给rabbitmq,需要关闭本次连接
connection.close()
执行代码:
[root@zfy2 rabbitmq]# python3 send1.py
已经发送了消息

- 消费者代码
import pika
credentials = pika.PlainCredentials("admin","000000")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.16.193',credentials=credentials))
channel = connection.channel()
# 声明一个队列(创建一个队列)
channel.queue_declare(queue='金品没')
def callback(ch, method, properties, body):
print("消费者接受到了任务: %r" % body.decode("utf-8"))
# 让程序报错,没有给生成者一个消息应答
int('asdfasdf')
# 我告诉rabbitmq服务端,我已经取走了消息
# 回复方式在这
ch.basic_ack(delivery_tag=method.delivery_tag)
# 关闭no_ack,代表给与服务端ack回复,确认给与回复
channel.basic_consume(callback,queue='金品没',no_ack=False) #no_ack=False 禁止不确认机制,代表需要给与服务端消息确认回复
channel.start_consuming()
执行代码:
[root@zfy2 rabbitmq]# python3 Receive1.py
消费者接受到了任务: '大郎,起来喝药了'
Traceback (most recent call last):
File "Receive1.py", line 23, in <module>
channel.start_consuming()
File "/usr/local/lib/python3.6/site-packages/pika/adapters/blocking_connection.py", line 1780, in start_consuming
self.connection.process_data_events(time_limit=None)
File "/usr/local/lib/python3.6/site-packages/pika/adapters/blocking_connection.py", line 716, in process_data_events
self._dispatch_channel_events()
File "/usr/local/lib/python3.6/site-packages/pika/adapters/blocking_connection.py", line 518, in _dispatch_channel_events
impl_channel._get_cookie()._dispatch_events()
File "/usr/local/lib/python3.6/site-packages/pika/adapters/blocking_connection.py", line 1403, in _dispatch_events
evt.body)
File "Receive1.py", line 15, in callback
int('asdfasdf')
ValueError: invalid literal for int() with base 10: 'asdfasdf'

可以看出当消费者虽然已经接收到消息但是没有给生产者做消息应答时,数据任然不会丢失
2.9 让队列以及消息支持持久化,防止异常崩溃,消息丢失
- 生产者代码,生产支持持久化的消息与队列
import pika
# 无密码
# connection = pika.BlockingConnection(pika.ConnectionParameters('123.206.16.61'))
# 有密码
credentials = pika.PlainCredentials("admin","000000")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.16.193',credentials=credentials))
channel = connection.channel()
# 声明一个队列(创建一个队列)
# 默认此队列不支持持久化,如果服务挂掉,数据丢失
# durable=True 开启持久化,必须新开启一个队列,原本的队列已经不支持持久化了
'''
实现rabbitmq持久化条件
delivery_mode=2
使用durable=True声明queue是持久化
'''
channel.queue_declare(queue='LOL',durable=True) #此步表示队列是支持持久化的参数
channel.basic_publish(exchange='',
routing_key='LOL', # 消息队列名称
body='我用双手成就你的梦想',
# 支持数据持久化
# 代表消息是持久的 2
properties=pika.BasicProperties(
delivery_mode=2,
)
)
connection.close()

- 消费者代码
import pika
# 建立与rabbitmq的连接
# 前四行都是连接到同一个rabbitmq服务端以及同一个队列
credentials = pika.PlainCredentials("admin","000000")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.16.193',credentials=credentials))
channel = connection.channel()
channel.queue_declare(queue="LOL",durable=True)
def callbak(ch,method,properties,body):
print("消费者取出了消息:%r"%body.decode("utf8"))
# 有消息来临,立即执行callbak,没有消息则夯住,等待消息
channel.basic_consume(callbak,queue="LOL",no_ack=True) #no_ack 不用确认
# 开始消费,接收消息
channel.start_consuming()

当我重启rabbitmq这个服务之后,没有设置持久化的几个消息队列都被内存给杀死,而设置了持久化的消息队列没有任然存活;

消息队列之rabbitmq学习使用的更多相关文章
- RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙
消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...
- 快速入门分布式消息队列之 RabbitMQ(1)
目录 目录 前言 简介 安装 RabbitMQ 基本对象概念 Message 消息 Producer 生产者 Consumer 消费者 Queue 队列 Exchange 交换机 Binding 绑定 ...
- Spring Boot 揭秘与实战(六) 消息队列篇 - RabbitMQ
文章目录 1. 什么是 RabitMQ 2. Spring Boot 整合 RabbitMQ 3. 实战演练4. 源代码 3.1. 一个简单的实战开始 3.1.1. Configuration 3.1 ...
- 消息队列系统 -- RabbitMQ
消息队列系统 -- RabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Que ...
- 消息队列之 RabbitMQ
https://www.jianshu.com/p/79ca08116d57 关于消息队列,从前年开始断断续续看了些资料,想写很久了,但一直没腾出空,近来分别碰到几个朋友聊这块的技术选型,是时候把这块 ...
- 转 消息队列之 RabbitMQ
转 https://www.jianshu.com/p/79ca08116d57 消息队列之 RabbitMQ 预流 2017.05.06 16:03* 字数 4884 阅读 80990评论 18喜欢 ...
- C# 消息队列之 RabbitMQ 进阶篇
Ø 简介 在之前的 C# 消息队列之 RabbitMQ 基础入门 中介绍了 RabbitMQ 的基本用法,其实要更全面的掌握 RabbitMQ 这个消息队列服务,我们还需要掌握以下内容: 1. ...
- 消息队列Rabbit MQ 学习第一篇
1 介绍 1.1RabbitMQ MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队 ...
- 快速入门分布式消息队列之 RabbitMQ(3)
目录 目录 前文列表 前言 通道 Channel 一个基本的生产者消费者实现 消费者 生产者 运行结果 应用预取计数 应用 ACK 机制 最后 前文列表 快速入门分布式消息队列之 RabbitMQ(1 ...
随机推荐
- matplotlib的学习10-Contours 等高线图
import matplotlib.pyplot as plt import numpy as np ''' 画等高线 数据集即三维点 (x,y) 和对应的高度值,共有256个点. 高度值使用一个 h ...
- MyBatis 与 Spring 的完美整合方法
MyBaits 整合 Spring MyBatis-Spring 项目 第一步:创建测试工程 第二步:引入依赖 jar 包 第三步:编写 Spring 配置文件 第四步:编写 MyBatis 配置文件 ...
- jquery ajax return不起作用
jquery的ajax方法:在success中使用return:来结束程序的时候,结束的只是success这个方法,也就是说success中的return的作用范围只是success: 如果要想在su ...
- js--数组的reduce()方法的使用介绍
前言 阅读文章之前先来考虑一个问题,如何去实现迭代一个数组,并且把它累加到一个值中?首先能够想到的是设置一个初始值,然后通过循环遍历这个数组,将数组中的值一项一项累加起来,然后返回这个设置的值就是最终 ...
- CentOS7 实战源码安装mysql5.7.17数据库服务器
CentOS7 实战源码安装mysql5.7.17数据库服务器 简介:实战演练mysql数据库服务器的搭建 mysql简介: mysql是一个开源的关系型数据库管理系统,现在是oracle公司旗下的 ...
- SQL Server中datetimeset转换datetime类型问题浅析
在SQL Server中,数据类型datetimeoffset转换为datetime类型或datetime2类型时需要特别注意,有可能一不小心你可能会碰到下面这种情况.下面我们构造一个简单案例,模拟一 ...
- active mq 简单配置
---恢复内容开始--- 在activemq.xml 配置activemq的响应配置: 配置消息持久化: <persistenceAdapter> <!-- ...
- 一道java算法题
12个人围成一圈,序号依次从1至12,从序号1开始顺时针依次数,数到7的人退出,下一个再依次从1开始数,求留下来的最后一个人的原始序号. public static void joseph(int[] ...
- 【探索之路】机器人篇(5)-Gazebo物理仿真环境搭建_让机器人运动起来
如果完成了前两步,那么其实我们已经可以去连接我们的现实中的机器人了. 但是,做机器人所需要的材料还没有到,所以我们这里先在电脑平台上仿真一下.这里我们用到的就算gazebo物理仿真环境,他能很好的和R ...
- Mac付费软件免费获取
很简单,充分利用微信公众号和某宝即可 1.微信公众号里面会分享"XX软件下载"或破解教程只要打开微信搜索就可以搜到. 顺便推荐几个公众号"GameRoom".& ...