介绍
RabbitMQ
是一个由erlang
开发的AMQP(Advanced Message Queue )的开源实现- RabbitMQ官网
适用场景
大型项目,分布式架构等模式下,解决项目模块之前的通信问题,降低模块之间的耦合性,增加架构体系的可扩展性,同时也解决异步处理,延时处理,并发等问题
- 任务异步处理
将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。
- 项目之间解耦合
MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合
- 流量削锋
流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛
应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。
- 消息通讯
消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等
- 日志处理
日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题
AMQP是什么 ?
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有RabbitMQ等。 来源于百度百科。
总结:AMQP是一套公开的消息队列协议,最早在2003年被提出,它旨在从协议层定义消息通信数据的标准格式,
为的就是解决MQ市场上协议不统一的问题。RabbitMQ就是遵循AMQP标准协议开发的MQ服务。
官方:http://www.amqp.org/
RabbitMQ应用场景结构图
RabbitMQ基础结构图
上传我们知道MQ担任的角色就是消息的传递,再看一下MQ到底有那些构成
基础结构图
组件说明:
- RabbitMQ(又称为:Broker):消息队列服务进程,主要包括交换机(Exchange)和队列(Queue)
- Exchange:消息队列交换机,按一定的规则将消息路由转发到特定队列,对消息进行过虑转发。
- Queue:消息队列,存储消息的队列,消息到达队列并安规则转发到指定的消费服务
- Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ
- Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。
注意:
Connection:就是一个TCP的连接。Producer和Consumer都是通过TCP连接到RabbitMQ Server的
Channels:虚拟连接。它建立在上述的TCP连接中。数据流动都是在Channel中进行的。也就是说,一般情况是程序起始建立TCP连接,第二步就是建立这个Channel
为什么使用Channel,而不是直接使用TCP连接?
对于OS来说,建立和关闭TCP连接是有代价的,频繁的建立关闭TCP连接对于系统的性能有很大的影响,而且TCP的连接数也有限制,这也限制了系统处理高并发的能力。但是,在TCP连接中建立Channel是没有上述代价的。对于Producer或者Consumer来说,可以并发的使用多个Channel进行Publish或者Receive。有实验表明,1s的数据可以Publish10K的数据包。当然对于不同的硬件环境,不同的数据包大小这个数据肯定不一样,但是我只想说明,对于普通的Consumer或者Producer来说,这已经足够了。如果不够用,你考虑的应该是如何细化split你的设计。
消息发布流程图
消息消费流程图
RabbitMQ与其它MQ简单比较
现有常用中间:ActiveMQ、RabbitMQ、RocketMQ、Kafka
RabbitMQ特点
RabbitMQ
算是AMQP
体系下最为重要的产品了,它基于Erlang
语言开发实现,高并发特性,性能较好RabbitMQ
支持AMQP
、XMPP
、SMTP
、STOMP
等多种协议,功能强大,适用于企业级开发- 吞吐量到万级,MQ功能比较完备,健壮、稳定、易用、跨平台、支持多种语言 如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX文档齐全
- 开源提供的管理界面非常棒,用起来很好用,社区活跃度高
- 更新频率相当高
RocketMQ特点
RocketMQ是阿里开源的一款分布式消息中间件,原名 Metaq,从3.0版本开始改名为 RocketMQ,是阿里参照 Kafka设计思想使用 Java语言实现的一套 MQ。RocketMQ将阿里内部多款 MQ产品(Notify、Metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下 MQ的架构,被阿里巴巴广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景。
- 保证严格的消息顺序。
- 提供针对消息的过滤功能。
- 提供丰富的消息拉取模式。
- 高效的订阅者水平扩展能力。
- 实时的消息订阅机制。
- 亿级消息堆积能力
优点:
- 可靠性:支持持久化,传输确认,发布确认等保证了MQ的可靠性。
- 灵活的分发消息策略:这应该是RabbitMQ的一大特点。在消息进入MQ前由Exchange(交换机)进行路由消息。分发消息策略有:简单模式、工作队列模式、发布订阅模式、路由模式、通配符模式。
- 支持集群:多台RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker。
- 多种协议:RabbitMQ支持多种消息队列协议,比如 STOMP、MQTT 等等。
- 支持多种语言客户端:RabbitMQ几乎支持所有常用编程语言,包括 Java、.NET、Ruby 等等。
- 可视化管理界面:RabbitMQ提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker。
- 插件机制:RabbitMQ提供了许多插件,可以通过插件进行扩展,也可以编写自己的插件。
缺点:
- 支持的客户端语言不多,目前是
Java
及C++
- 社区活跃度一般,没有在
MQ
核心中去实现JMS
等接口,有些系统要迁移需要修改大量代码
Kafka 特点
Kafka是 Apache下的一个开源流处理平台,由 Scala和 Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作(网页浏览,搜索和其他用户的行动)流数据。Kafka的目的是通过 Hadoop的并行加载机制来统一线上和离线的消息处理,也是为了通过集群来提供实时的消息。
Kafka
具有以下特性:
- 快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化
- 高吞吐:在一台普通的服务器上既可以达到 10W/s 的吞吐速率
- 高堆积:支持 topic下消费者较长时间离线,消息堆积量大
- 完全的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,通过 Zookeeper可以自动实现更加复杂的负载均衡
- 支持 Hadoop数据并行加载
优点:
- 性能卓越,单机写入TPS约在百万条/秒,最大的优点,就是吞吐量高
- 时效性ms级可用性非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用
- 消费者采用Pull方式获取消息,消息有序,通过控制能够保证所有消息被消费且仅被消费一次
- 有优秀的第三方Kafka Web管理界面Kafka-Manager
- 在日志领域比较成熟,被多家公司和多个开源项目使用
- 功能支持:功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用
缺点:
Kafka
单机超过64
个队列/分区,Load
会发生明显的飙高现象,队列越多,load
越高,发送消息响应时间变长,使用短轮询方式,实时性取决于轮询间隔时间,消费失败不支持重试- 支持消息顺序,但是一台代理宕机后,就会产生消息乱序,社区更新较慢
中间件选择
Kafka:
Kafka
主要特点是基于Pull
的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输,适合产生大量数据的互联网服务的数据收集业务。大型公司建议可以选用,如果有日志采集功能,肯定是首选kafka
了
RocketMQ:
天生为金融互联网领域而生,对于可靠性要求很高的场景,尤其是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。
RoketMQ
在稳定性上可能更值得信赖,这些业务场景在阿里双11已经经历了多次考验,如果你的业务有上述并发场景,建议可以选择RocketMQ
RabbitMQ:
结合erlang语言本身的并发优势,性能好时效性微秒级,社区活跃度也比较高,管理界面用起来十分方便,如果你的数据量没有那么大,中小型公司优先选择功能比较完备的RabbitMQ
RabbitMQ六种工作模式
1. 简单模式
2. work queues
- work queues 相比简单的模式下,多了一个消费端,多个消费端,共同消费同一个队列中的消息
- 应用场景:对于数据量参数比较大,且又有一定时效性的场景适合,扩展消费端提高处理速度
注意:
1、一条消息只会被一个消费者接收;
2、rabbit采用轮询的方式将消息是平均发送给消费者的;
3、消费者在处理完某条消息后,才会收到下一条消息。
3. publish/subscribe
工作模式 :发布订阅模式
![](https://zhangyu-blog.oss-cn-beijing.aliyuncs.com/img/image-20220310133939942.png#crop=0&crop=0&crop=1&crop=1&id=oVlPj&originHeight=413&originWidth=983&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
注意:
使用场景:
例如:用户通知,当用户充值成功或转账完成系统通知用户,通知方式有短信、邮件多种方法
**exchange**种类:
- Fanout:广播,将消息交给所有绑定到交换机的队列
- Direct:定向,将消息交给符合routingKey的队列
- Topic:主题(使用通配符),将消息交给符合routing pattern(路由模式)的队列
publish/subscribe与work queues比较
1. 区别:
- work queues不用定义交换机,而publish/subscribe需要定义交换机。
- publish/subscribe的生产方是面向交换机发送消息,work queues的生产方是面向队列发送消息(底层使用默认
交换机)。 - publish/subscribe需要设置队列和交换机的绑定,work queues不需要设置,实质上work queues会将队列绑
定到默认的交换机 。
2. 相同:
- 两者实现的发布/订阅的效果是一样的,多个消费端监听同一个队列不会重复消费消息
- 实际项目中相比使用
publish/subscribe
多发布订阅模式比工作队列模式更强大,并且发布订阅模式可以指定特定的交换机,灵活
4. routing路由模式
也称之为direct模式
在交换机fanout
模式中,一条消息会被发布到所有订阅的队列,在某些场景下,我们希望不同的消息被不同的队列消费,就可以使用direct
模式【其实是交换机根据执行的路由key(RoutingKey)转发到指定的队列中】
direct模式:
- 队列与交换机的绑定,不能是任意绑定了,而是要指定一个
RoutingKey
(路由key) - producer向 Exchange发送消息时,也必须指定消息的
RoutingKey
。 - Exchange不再把消息交给每一个绑定的队列,而是根据消息的
Routing Key
进行判断,只有队列的Routingkey
与消息的Routing key
完全一致,才会接收到消息
direct交换机和fanout交换机的差异:
- fanout交换机将消息路由给每个与其绑定的队列
- direct交换机根据routingkey判断路由给那个队列
- 如果多个队列具有相同的routingkey,则与fanout功能相似
5. topics主题模式
Topic
类型的Exchange
与Direct
相比,都是可以根据RoutingKey
把消息路由到不同的队列。只不过Topic
类型Exchange
可以让队列在绑定Routing key
的时候使用通配符!
Routingkey
一般都是有一个或多个单词组成,多个单词之间以.
分割,例如: item.insert
通配符规则:
#
:匹配一个或多个词
*
:匹配不多不少恰好1个词
案例:
根据用户的通知设置去通知用户,设置接收Email的用户只接收Email,设置接收sms的用户只接收sms,设置两种
通知类型都接收的则两种通知都有效。
6. Headers模式
Headers模式
下它的路由不是用routingKey进行路由匹配,而是在匹配请求头中所带的键值进行路由- 创建队列需要设置绑定的头部信息,有两种模式:全部匹配和部分匹配
- 交换机会根据生产者发送过来的头部信息携带的键值去匹配队列绑定的键值,路由到对应的队列
对MQ的基本架构组成,工作模式流程有一个大致的熟悉