消息队列之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学习使用的更多相关文章

  1. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙

    消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...

  2. 快速入门分布式消息队列之 RabbitMQ(1)

    目录 目录 前言 简介 安装 RabbitMQ 基本对象概念 Message 消息 Producer 生产者 Consumer 消费者 Queue 队列 Exchange 交换机 Binding 绑定 ...

  3. Spring Boot 揭秘与实战(六) 消息队列篇 - RabbitMQ

    文章目录 1. 什么是 RabitMQ 2. Spring Boot 整合 RabbitMQ 3. 实战演练4. 源代码 3.1. 一个简单的实战开始 3.1.1. Configuration 3.1 ...

  4. 消息队列系统 -- RabbitMQ

    消息队列系统 -- RabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Que ...

  5. 消息队列之 RabbitMQ

    https://www.jianshu.com/p/79ca08116d57 关于消息队列,从前年开始断断续续看了些资料,想写很久了,但一直没腾出空,近来分别碰到几个朋友聊这块的技术选型,是时候把这块 ...

  6. 转 消息队列之 RabbitMQ

    转 https://www.jianshu.com/p/79ca08116d57 消息队列之 RabbitMQ 预流 2017.05.06 16:03* 字数 4884 阅读 80990评论 18喜欢 ...

  7. C# 消息队列之 RabbitMQ 进阶篇

    Ø  简介 在之前的 C# 消息队列之 RabbitMQ 基础入门 中介绍了 RabbitMQ 的基本用法,其实要更全面的掌握 RabbitMQ 这个消息队列服务,我们还需要掌握以下内容: 1.   ...

  8. 消息队列Rabbit MQ 学习第一篇

    1 介绍  1.1RabbitMQ MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队 ...

  9. 快速入门分布式消息队列之 RabbitMQ(3)

    目录 目录 前文列表 前言 通道 Channel 一个基本的生产者消费者实现 消费者 生产者 运行结果 应用预取计数 应用 ACK 机制 最后 前文列表 快速入门分布式消息队列之 RabbitMQ(1 ...

随机推荐

  1. Web服务器-并发服务器-长连接(3.4.4)

    @ 目录 1.说明 2.代码 关于作者 1.说明 每次new_socket都被强制关闭,造成短连接 所提不要关闭套接字 但是不关闭的话,浏览器不知道发完没有啊 此时用到header的属性Content ...

  2. SpringBoot从入门到精通教程(四)

    前端时间整合SSM ,发现了一个现象,在整合的时候 配置文件过于复杂. 1.建工程,建目录,导入jar包. 2.配置 数据源 映射信息 等等 ... 3. 还有 各种 拦截器,控制器 ,头都大了... ...

  3. Linux下安装ffmpeg,视频格式转换

    下载ffmpeg 从ffmpeg官网:http://ffmpeg.org/download.html 下载最新的ffmpeg安装包,然后通过如下命令解压: 解压 ffmpeg-*.tar.bz2 文件 ...

  4. Python三个处理excel表格的库

    三个向excel表格写入数的库:xlwt,xlsxwriter,openpyxl,代码如下: 1 #第一个库,xlwt,不能写超过256列的表格 2 import xlwt 3 4 #新建workbo ...

  5. windows服务器安装exe文件出错

    今天在安装exe文件的时候出现了错误,记录如下: 服务器环境为windows 2016数据中心标准英文版.要安装的软件为***.exe.按照在本地电脑上安装的方法,直接双击打开,然后错误出现如下图: ...

  6. 使用CDN后如何配置Apache使其记录访客真实IP

    今天想看看哪些地区的人访问过我的网站,于是打开Apache网站响应日志,把访客IP复制到百度,发现搜到的全部都是我是用的CDN的节点IP,真实的访客IP并没有被记录. 如图所示,上面的103.45.7 ...

  7. C#中的深度学习(五):在ML.NET中使用预训练模型进行硬币识别

    在本系列的最后,我们将介绍另一种方法,即利用一个预先训练好的CNN来解决我们一直在研究的硬币识别问题. 在这里,我们看一下转移学习,调整预定义的CNN,并使用Model Builder训练我们的硬币识 ...

  8. Linux嵌入式学习-USB端口号绑定

    由于ubuntu USB设备号为从零开始依次累加,所以多个设备每次开机后设备号不固定,机器人每次开机都要蛋疼的按顺序插, 在网上找到一种方法:udev的规则 udev的规则说明,可以参考博客说明:ht ...

  9. java Swing组件随着窗口拖动等比移动或等比放大

    实现原理很简单, 1清空布局(使用绝对布局) 2添加监听器(监听窗口是否被拖动) 3在监听器里面动态调整 组件的位置 效果如下: 拖动之后效果: 代码实现: import java.awt.Event ...

  10. 使用pdf.js aspose各种文档转PDF 版本对应license.xml 去水印破解

    在使用pdf.js途中,使用aspose转换的文件一直有水印,在网上找了许多破解办法都是已经失效的,于是乎,就查看了一下jar的源码,找到了版本对应的破解字符(如下):对应版本为 aspose-wor ...