什么是AMQP?
- 是一种为中间件设计的应用层标准高级的消息队列协议,用来统一数据在客户端与服务端交互的格式,不受任何中间件产品和其他条件所限制。
MQ三大主要功能
- 异步
- 解耦
- 削峰
一,RabbitMQ介绍
-
介绍
- RabbitMQ是基于AMQP的一款开源的消息管理系统
- 可以用来做消息中间件
- 支持主流操作系统:Linux,Windows,MacOX等
- 多种开发语言支持,java,python,ruby,PHP,node.js等
-
RabbitMQ工作基本流程
-
Broker: 是一个或者是RabbitMQ集群
-
Virtual Host: Broker里面由交换机(Exchange)和消息队列(Queue)组成,这两个合成整体叫虚拟主机(Virtual Host)一个rabbitMQ有7个交换机
-
Binding: 队列要和交换机进行绑定后才能进行接收消息
-
Channel: 信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真是实的TCP连接内地虚拟连接,AMQP命令都是通过通信到发出去的,不管是发布消息,订阅,队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁TCP都是非常昂贵的开销,所以引入了信道的概念,以复用一条TCP连接。
-
发送消息: 发布者(publisher)通过连接通道(Channel)发送消息给交换机(Exchange),交换机再将消息分发给消息队列(队列可以是一个或者多个)
-
接收消息: 接收者(Consumer)通过连接通道(Channel)连接到消息队列进行取消息
-
补充:
-
为什么要有信道:
- 在每次连接取完数据时会断开连接,不能同时取多个队列的消息,还消耗性能
- 一个链接里可以有多个信道,不同信道可以通过不同队列取不同的消息
- 通道使用完只关闭通道即可
-
消息是由消息头和消息体组成。
- 消息体是不透明的,消息头由一系列可选属性组成,比如:routing-key(路由键),priority(相对于其他消息的优先权),delivery-mode(指出该消息可能需要持久性存储)等
- 并不是交换机和路由连接成功队列就一定能拿到数据,队列可以根据routing-key(路由键)只接收添加商品的消息,修改删除则可以使用其他队列进行接收存储
-
在Broker中有6种消息传递模式点击这里查看
-
-
二,RabbitMQ 常用命令及界面
-
常用命令
- 启动服务:systemctl start rabbitmq-server.service
- 停止服务:systemctl stop rabbitmq-server.service
- 查看服务状态:systemctl status rabbitmq-server.service
- 重启服务:systemctl restart rabbitmq-server.service
-
管理界面
-
在安装rabbitmq时需要关闭防火墙:systemctl stop firewalld.service
-
启动后台管理界面:rabbitmq-plugins enable rabbitmq-management
-
访问页面:http://127.0.0.1:15367/ 用户默认不允许远程连接不支持使用具体ip登录
-
默认用户名和密码:guest
-
-
账号管理命令
- 添加管理员账号密码:rabbitmqctl adduser admin admin
- 分配账号角色:rabbitmqctl set_user_tags admin adminstrator(设置管理员权限,此账号可以远程登录,其他还有后台监控权限等等在页面也可以添加)
- 修改密码:rabbitmqctl change_password admin 123456
- 查看用户列表:rabbitmqctl list_users
-
端口:
- 5672:rabbitmq的编程语言客户端连接端口
- 15672:rabbitmq管理界面端口
- 25672:rabbitmq集群的端口
三,发布者的确认
-
概念
- 在通道上启用发布者确认后,代理将异步确认生产者是否将消息成功投递到队列中。(默认状态是关闭的)
-
使用步骤
-
import pika conn = pika.BlockingConnection( pika.ConnectionParameters(host='localhost') ) channel = conn.channel() channel.confirm_delivery() #另一种确认方法 channel.basic_ack(delivery_tag=0,multiple=False)
-
confirm_delivery() 表示
(参照网站:https://pika.readthedocs.io/en/stable/modules/adapters/blocking.html#)- 当RabbitMQ收到消息时,将返回basic.ack(收到消息)或basic.nack(未收到消息).
- 缺点是但是,这不能保证消息已成功传递到队列
- 注意:
- Connection()类中有一个publisher_confirms()方法是指定活动连接是否可以使用发布者确认。
-
basic_ack(delivery_tag=0,multiple=False)
- delivery_tag:消费者的标签
- multiple=False只能传递单个标签反之可以传递多个消费者标签
- 该消息可以用来确认一个或多个消息。
- 由服务器发送时,此方法以确认方式确认在通道上使用Publish方法发布的一条或多条消息。
- 当由客户端发送时,此方法确认通过Deliver或Get-Ok方法传递的一条或多条消息。
- 该确认可以针对单个消息或一组消息,直到并包括特定消息。
-
四,消费者消息确认机制(ACK)
-
概念
- 用来确认消费者是否成功消费了队列中的消息。
-
确认过程
- 消息一旦被消费者接收,队列中的消息就会被删除
- 当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。
-
回执ACK有两种:
(参照网站:https://pika.readthedocs.io/en/stable/modules/adapters/blocking.html#)
-
自动ACK:消息一旦被接收,消费者自动发送ACK(适合不太重要的数据)
connection = pika.BlockingConnection( pika.ConnectionParameters(host='localhost')) channel = connection.channel() channel.exchange_declare(exchange='logs', exchange_type='fanout') result = channel.queue_declare(queue='', exclusive=True) channel.queue_bind(exchange='logs', queue=result.method.queue) def callback(ch, method, properties, body): print(" [x] %r" % body) #消费者自动确认ACK(默认情况下是不自动确认) channel.basic_consume(auto_ack=True)
-
手动ACK:消息接收后,不会发送ACK,需要手动调用(手动应答-需要我们开发人员手动去调用ack方法去告诉服务已经收到。)
#连接创建频道使用方法同上 channel.basic_ack(delivery_tag=0,multiple=False) #delivery_tag:消费者的标签 #multiple=False只能传递单个标签反之可以传递多个消费者标签 #当由客户端发送时,此方法确认通过Deliver或Get-Ok方法传递的一条或多条消息。
-
五,RabbitMQ优缺点
六,RabbitMQ应用场景
-
异步处理
- 比如用户注册时的确认邮件、短信等交由rabbitMQ进行异步处理
-
应用解耦
- 比如收发消息双方可以使用消息队列,具有一定的缓冲功能
-
流量削峰
- 一般应用于秒杀活动,可以控制用户人数,也可以降低流量
-
日志处理
- 将info、warning、error等不同的记录分开存储
七,常见的MQ产品
- ActiveMQ:基于JMS
- RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好
- RocketMQ:基于JMS,阿里巴巴产品,目前交由Apache基金会
- Kafka:分布式消息系统,高吞吐量,处理日志,Scala和java编写