RabbitMQ是实现了高级消息队列协议CAMQP)的开源消息代理软件, 也称为面向消息的中间件
AMQP是Advanced Message Queuing Protocol的简称,它是一个面向消息中间
件的开放式标准应用层协议。 它定义了以下这些特性:
消息方向
消息队列
消息路由(包括点到点和发布-订阅模式)
可靠性
安全性
AMQP要求消息的提供者和客户端接收者的行为要实现对不同供应商可以用
相同的方式(比如SMTP、 HTTP、FTP等)
Broker: 可以理解为消息队列服务器的实体, 它是 一 个 中间件应用, 负责接收消息
生产者的消息, 然后将消息发送至消息接收者或者其他的Broker。
Exchange: 消息交换机, 是消息第一 个到达的地方, 消息通过它指定的路由规则,
分发到不同的消息队列中去。
Queue: 消息队列, 消息通过发送和路由之后最终到达的地方, 到达Queue的消息
即进入逻辑上等待消费的状态。 每个消息都会被发送到 一 个或多个队列 。
Binding: 绑定,它的作用就是把Exchange和Queue按照路由规则绑定起来, 也就
是Exchange和Queue之间的虚拟连接 。
Routing Key: 路由关键字,Exchange根据这个关键字 进行消息投递。
Virtual host: 虚拟主机, 它是对Broker的虚拟划分, 将消费者、 生产者 和它们依赖
的AMQP相关结构 进行隔离,一般都是为了安全考虚。比如,我们可以在 一 个Broker
中设置多个虚拟主机, 对不同用户进行权限的分离 。
Connection: 连接, 代表生产者、 消费者、 Broker之间进行通信的物理网络。
Channel: 消息通道,用千连接生产者 和 消费者的逻辑结构 。在客户端的每个连接里,
可建立多个Channel, 每个Channel代表 一 个会话任务, 通过Channel可以隔离同 一
连接中的不同交互内容。
Producer: 消息生产者, 制造消息并发送消息的程序。
Consumer: 消息消费者, 接收消息并处理消息的程序。
消息投递到队列的整个过程大致如下:
1 客户端连接到消息队列服务器,打开一 个Channel 。
2. 客户端声明一个Exchange,并设置相关属性。
3 客户端声明一个Queue, 并设置相关属性。
4 客户端使用Routing Key, 在Exchange和Queue之间建立好绑定关系。
5 客户端投递消息到Exchange 。
6. Exchange接收到消息后,根据消息的Key和已经设置的Binding,进行消息路由,
将消息投递到一 个或多个Queue里。
Exchange也有几种类型。
1. Direct交换机:直接交换器,工作方式类似于单播,Exchange会将消息发送完全匹配ROUTING_KEY的Queue
那么客户端提交的消息,只有设置了Key为abc 的才会被投递到队列。
2. Topic交换机:主题交换器,工作方式类似于组播,Exchange会将消息转发和ROUTING_KEY匹配模式相同的所有队列,比如,ROUTING_KEY为user.stock的Message会转发给绑定匹配模式为 * .stock,user.stock, * . * 和#.user.stock.#的队列。( * 表是匹配一个任意词组,#表示匹配0个或多个词组)
3. Fanout交换机:广播式交换器,不管消息的ROUTING_KEY设置为什么,Exchange都会将消息转发给所有绑定的Queue
4.Headers exchange:首部交换机 ,如果消息的头部信息和binding的参数表中匹配的话,消息将会路由到该队列。
Binding
所谓绑定就是将一个特定的 Exchange 和一个特定的 Queue 绑定起来。Exchange 和Queue的绑定可以是多对多的关系
RabbitMQ支持消息的待久化,也就是将数据写在磁盘上。为了数据安全考虑,大多数
情况下都会选择持久化。 消息队列持久化包括3个部分:
1. Exchange 持久化,在声明时指定durable => 1。
2. Queue 待久化,在声明时指定durable => 1。
3 消息持久化,在投递时指定delivery_mode => 2 (1是非持久化)。
如果Exchange和Queue都是持久化的,那么它们之间的Binding也是持久化的。 如果
Exchange和Queue两者之间有一 个是待久化的,一个是非持久化的, 就不允许建立绑定。
通信过程
假设P1和C1注册了相同的Broker,Exchange和Queue。P1发送的消息最终会被C1消费。基本的通信流程大概如下所示:
P1生产消息,发送给服务器端的Exchange
Exchange收到消息,根据ROUTINKEY,将消息转发给匹配的Queue1
Queue1收到消息,将消息发送给订阅者C1
C1收到消息,发送ACK给队列确认收到消息
Queue1收到ACK,删除队列中缓存的此条消息
Tags 标签是 RabbitMQ 中的角色分类, 共有下面几种:
1:none: 不能访问 management plugin。
2:management: 用户可以通过 AMQP 做的任何事外加如下内容:
列出自己可以通过 AMQP 登入的 virtual hosts。
查看自己的 virtual hosts 中的 queues、 exchanges 和 bindings。
查看和关闭自己的 channels 和 connections。
查看有关自己的 virtual hosts 的“ 全局 ” 统计信息, 包含其他用户在这些 virtualhosts 中的活动。
3:policymaker: management 可以做的任何事外加如下内容:
查看、 创建和删除自己的 virtual hosts 所属的 policies 和 parameters。
4:monitoring: management 可以做的任何事外加如下内容:
列出所有 virtual hosts, 包括它们不能登录的 virtual hosts。
查看其他用户的 connections 和 channels。
查看节点级别的数据, 如 clustering 和 memory 的使用情况
查看真正的关于所有virtual hosts的全局的统计信息
5:administrator: policymaker和monitoring可以做的任何事外加如下内容 :
创建和删除virtual hosts。
查看、 创建和删除users。
查看、 创建和删除permissions。
关闭其他用户的connections。
注解:
创建消息消费者 Receiver。 通过@RabbitListener 注解定义该类对队列的监听, 并用@Rabb江Handler 注解来指定对消息的处理方法
创建消息生产者 Sender。 通过注入AmqpTemplate 接口的实例来实现消息的发送,AmqpTemplate 接口定义了 一套针对 AMQP 协议的基础操作。
Kafka:是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache定级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
RabbitMQ:是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
RocketMQ:是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。
在同步发送场景中,三个消息中间件的表现区分明显:
Kafka的吞吐量高达17.3w/s,不愧是高吞吐量消息中间件的行业老大。这主要取决于它的队列模式保证了写磁盘的过程是线性IO。此时broker磁盘IO已达瓶颈。
RocketMQ也表现不俗,吞吐量在11.6w/s,磁盘IO %util已接近100%。RocketMQ的消息写入内存后即返回ack,由单独的线程专门做刷盘的操作,所有的消息均是顺序写文件。
RabbitMQ的吞吐量5.95w/s,CPU资源消耗较高。它支持AMQP协议,实现非常重量级,为了保证消息的可靠性在吞吐量上做了取舍。我们还做了RabbitMQ在消息持久化场景下的性能测试,吞吐量在2.6w/s左右