文章目录
第一章 消息中间件
1.1 应用场景
- 异步任务处理:将耗时的任务放入消息队列,异步处理,提高系统的响应速度。
- 系统解耦:通过消息队列,系统之间解耦,实现松耦合的架构,方便扩展和维护。
- 数据同步:通过消息队列实现不同系统之间的数据同步,确保数据的一致性。
- 削峰填谷:通过消息队列,可以控制系统的并发压力,防止服务过载。
- 日志收集:将日志信息发送到消息队列,实现集中式的日志管理和统计分析。
1.2 各消息中间件优缺点和对比
1.2.1 ActiveMQ
我们先看
ActiveMQ
。其实一般早些的项目需要引入消息中间件,都是使用的这个MQ,但是现在用的确实不多了,说白了就是有些过时了。我们去它的官网看一看,你会发现官网已经不活跃了,好久才会更新一次。
它的单机吞吐量是万级,一些小的项目已经够用了,但对于高并发的互联网项目完全不够看。
在高可用上,使用的主从架构的实现。
在消息可靠性上,有较低的概率会丢失数据。
综合以上,其实这个产品基本可以弃用掉了,我们完全可以使用RabbitMQ来代替它。
1.2.2 RabbitMQ
RabbitMQ
出现后,国内大部分公司都从ActiveMQ切换到了RabbitMQ,基本代替了activeMQ的位置。它的社区还是很活跃的。
它的单机吞吐量也是万级,对于需要支持特别高的并发的情况,它是无法担当重任的。
在高可用上,它使用的是镜像集群模式,可以保证高可用。
在消息可靠性上,它是可以保证数据不丢失的,这也是它的一大优点
。
同时它也支持一些消息中间件的高级功能,如:消息重试、死信队列等。
但是,它的开发语言是erlang,国内很少有人精通erlang,所以导致无法阅读源码。
对于大多数中小型公司,不需要面对技术上挑战的情况,使用它还是比较合适的。而对于一些BAT大型互联网公司,显然它就不合适了。
1.2.3 RocketMQ
接下来我们来讨论一下我比较喜欢的
RocketMQ
,它是阿里开源的消息中间件,久经沙场,非常靠谱。
它支持高吞吐量,能达到10万级,能承受互联网项目高并发的挑战。
在高可用上,它使用的是分布式架构,可以搭建大规模集群,性能很高。
在消息可靠性上,通过配置,可以保证数据的绝对不丢失。
同时它支持大量的高级功能,如:延迟消息、事务消息、消息回溯、死信队列等等。
它非常适合应用于java系统架构中,因为它使用java语言开发的,我们可以去阅读源码了解更深的底层原理。
目前来看,它没有什么特别的缺点,可以支持高并发下的技术挑战,可以基于它实现分布式事务,大型互联网公司和中小型公司都可以选择使用它来作为消息中间件使用,如果我来做技术选型,我首选的中间件就是它。
1.2.4 Kafka
kafka的吞吐量被公认为中间件中的翘楚,单机可以支持十几万的并发,相当强悍。
在高可用上同样支持分布式集群部署。
在消息可靠性上,如果保证异步的性能,可能会出现消息丢失的情况,因为它保存消息时是先存到磁盘缓冲区的,如果机器出现故障,缓冲区的数据是可能丢失的。
它的功能非常的单一,就是消息的接收与发送,因此不适合应用于许多场景。
它在行业内主要应用于大数据领域,使用它进行
用户行为日志的采集和计算
。
所以,如果没有大数据的需求,一般不会选择它
。
引用:消息中间件面试题:消息队列的优缺点,区别
第二章 RabbitMQ_基础
2.1 为什么选择RabbitMQ
ActiveMQ
,性能不是很好,因此在高并发的场景下,直接被pass掉了。它的 Api 很完善,在中小型互联网公司可以去使用。kafka
,主要强调高性能,如果对业务需要可靠性消息的投递的时候。那么就不能够选择kafka了。但是如果做一些日志收集呢,kafka还是很好的。因为kafka的性能是十分好的。RocketMQ
,它的特点非常好。它高性能、满足可靠性、分布式事物、支持水平扩展、上亿级别的消息堆积、主从之间的切换等等。MQ的所有优点它基本都满足。但是它最大的缺点:商业版收费。因此它有许多功能是不对外提供的。
2.2 RabbitMQ简介
RabbitMQ 是一个由
Erlang
语言开发的 AMQP 的开源实现。AMQP :Advanced Message Queue Potocal,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。RabbitMQ最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
2.3 RabbitMQ架构
Broker
(服务器):即RabbitMQ Server,也叫Broker server,接收和分发消息的应用,保证数据能够按照指定的方式进行传输。Connection
(连接):Producer/Consumer 和 broker 之间的TCP
连接,在消息发送时必须要先建立与RabbitMQ服务器的连接。Channel
(信道):建立在Connection中,消息是基于Channel传递的,Channel之间是完全隔离的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销;如果每一次访问RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP Connection的开销将是巨大的,效率也较低。VirtualHost
(虚拟主机):exchange/queue是属于某个VirtualHost的,VirtualHost属于某个用户的;VirtualHost可以分配用户在创建交换机或队列时可以指定其属于哪个虚拟主机,方便用户管理交换机和队列。Producer
(生产者): 消息的生产者,数据的发送方。消息生产者连接RabbitMQ服务器然后将消息投递到Exchange。Exchange
(交换机):生产者将消息发送到 Exchange(交换器),由 Exchange将消息路由到一个或多Queue 中(或者丢弃)。Exchange 并不存储消息。RabbitMQ 中的 Exchange 有direct
、fanout
、topic
、headers
四种类型,每种类型对应不同的路由规则。Queue
(队列):是RabbitMQ的内部对象,用于存储消息。消息消费者就是通过订阅队列来获取消息;RabbitMQ 中的消息都只能存储在Queue中,生产者生产消息并最终投递到Queue 中,消费者可以从 Queue 中获取消息并消费。多个消费者可以订阅同一个Queue,这时 Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。
2.4 交换机类型
2.4.1 Direct Exchange(直连交换机)
直连交换机的特点是消息队列通过routingKey与交换机进行绑定,相同的routingKey会获得相同的消息。一个队列可以通过多个不同的routingKey与交换机进行绑定。不同的队列也可以通过相同的routingKey绑定交换机。
2.4.2 Fanout Exchange(扇出交换机)
扇出交换机的特点是类似于广播,只要队列与该类型的交换机绑定,所有发送到该交换机的信息都会被转发到所有与之绑定的队列,与routingKey无关。
2.4.3 Topic Exchange(主题交换机)
应用范围最广的交换机类型,消息队列通过消息主题与交换机绑定。一个队列可以通过多个主题与交换机绑定,多个消息队列也可以通过相同消息主题和交换机绑定。并且可以通过通配符(
*
或者
#
)进行多个消息主题的适配。
消息主题的一般格式为xxx.xxx.xxx(x为英文字母,每个单词用英文句号隔开)。*通配符可以适配一个单词,#可以适配零个或者多个单词。
2.4.4 Header Exchenge(头交换机)
与routingKey无关,匹配机制是匹配消息头中的属性信息。在绑定消息队列与交换机之前声明一个map键值对,通过这个map对象实现消息队列和交换机的绑定。当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。
匹配规则x-match有下列两种类型:
- x-match = all :表示
所有的键值对都匹配
才能接受到消息 - x-match = any :表示
只要有键值对匹配
就能接受到消息
引用:
1.Rabbitmq的四种类型交换机
2.5 RabbitMQ工作模式
RabbitMQ官网地址:里面有介绍RabbitMQ的工作模式。
2.5.1 Hello World
简单模式中表现为一个生产者对应一个消费者,生产者(Producer)生产消息发送到队列,消费者(Consumer)监听此队列,进行消息的消费;
2.5.2 Work Queues
Work模式与Simple模式几乎是一模一样的,只不过我们在只有一个Producer和一个Consumer时习惯把这种模式称为Simple模式,而当一个Producer有多个Consumer时我们把这样的模式成为Work模式,因此Work模式和Simple模式的代码是一模一样的,只不过是多个Consumer监听同一个队列而已(一个队列下的Consumer是
竞争关系
);
2.5.3 Publish/Subscribe
在发布订阅模式中,Producer发送消息到指定的交换机(Exchange)中,由Exchange绑定不同的Queues,消费者依旧监听这些队列进行消费(work模式使用的是默认的交换机,空字符串"")。
一个Exchange可以有
direct
、
topic
、
headers
、
fanout
四种类型,不同类型的Exchange具备不同的消息路由功能,
Pub/Sub模式
则重点强调的是
fanout
类型的Exchange交换模式,Publish/Subscribe模式也叫分列模式;
需要注意的两点:
1、work、simple也会有交换机,他们使用的是默认的交换机
2、Exchange还可以绑定到另一个Exchange上
2.5.4 Routing
Publish/Subscribe 订阅强调的是
Fanout
类型的Exchange,
Routing模式
则强调的是Exchange的
direct
模式,Routing模式也叫直连模式;
如上图所示,如果消息的路由键是orange,则此消息只会到队列1上。实际工作中,90%都是使用的此模式。
2.5.5 Topics
Topics
模式也叫主题模式,相比于订阅模式,该模式下的Exchange在绑定Queues时可以指定的一定的通配符,这些通配符指定了路由的规则;
- 符号
#
:匹配零个或多个词。(0个或多个) - 符号
*
:匹配不多不少一个词。(必须是一个,0个不行)
2.5.6 RPC
《RabbitMQ系列教程-第四章-06-RabbitMQ工作模式之RPC模式》
2.5.7 Publisher Confirms
这部分比较复杂,放到后面介绍。
第三章 RabbitMQ_进阶
3.1 消息可靠性
参见此篇博客。
如何确保RabbitMQ消息的可靠性?
- 开启生产者确认机制,确保生产者的消息能到达队列。
- 开启持久化功能,确保消息未消费前在队列中不会丢失。
- 开启消费者确认机制为auto,由spring确认消息处理成功后完成ack。
- 开启消费者失败重试机制,并设置MessageRecoverer,多次重试失败后将消息投递到异常交换机,交由人工处理。
3.2 消费端限流
配置一个
prefetch
参数,限定每次消费者消费消息的数量。
3.3 消息超时
参见此篇博文。
3.4 死信和死信队列
死信
,顾名思义就是无法被消费的消息。一般来说,Producer 将消息投递到 Broker 或者直接到 Queue 里了,Consumer 从 Queue 取出消息进行消费,但某些时候由于特定的原因导致 Queue 中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列。
应用场景:为了保证订单业务的消息数据不丢失,需要使用到 RabbitMQ 的死信队列机制,当消息消费发生异常时,将消息投入到死信队列中。
版权归原作者 珍珠是蚌的眼泪 所有, 如有侵权,请联系我们删除。