文章目录
本文借鉴了新手也能看懂,消息队列其实很简单中有关消息队列的部分内容
一.消息队列
消息队列是一个存放消息的容器,当我们需要使用消息的时候可以取出消息供自己使用。分布式系统中经常要使用到消息队列,使用消息队列主要是为了达成两个目的,第一点是通过异步处理提高系统性能,消息队列有削峰、减少响应所需时间的功能;第二点是降低系统耦合性。
1.1 通过异步处理提高系统性能
如上图,在不使用消息队列服务器的时候,用户请求后一直要等到数据库写入完成后才能响应,因此用户必须要等待很长时间,服务器的负载也会因此飙升。
但是在使用消息队列之后,用户的请求数据发送给消息队列之后立刻返回响应,然后数据库再从消息队列中读取数据写入数据库,这样用户请求处理的过程就变成了一个异步的过程。由于消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),因此响应速度得到大幅改善。
通过以上分析我们可以得出消息队列具有很好的削峰作用的功能——即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。 举例:在电子商务一些秒杀、促销活动中,合理使用消息队列可以有效抵御促销活动刚开始大量订单涌入对系统的冲击。如下图所示:
1.2 降低系统耦合性
在不使用消息中间件的场合下,如果业务逻辑比较复杂,那么业务关系之间的关系就会非常混乱,难以管理,复用性也非常差加入消息中间件以后,生产者统一到消息队列中发布服务,消费者订阅服务,服务之间的调用关系可以在消息队列中非常清晰的看到,当系统的某一个模块需要升级或者有新的功能模块需要加入进来都会非常方便
1.3 常用的几种消息队列及其比较
ActiveMQ
社区算是比较成熟,但是较目前来说,ActiveMQ 的性能比较差,而且版本迭代很慢,不推荐使用。
RabbitMQ
在吞吐量方面虽然稍逊于 Kafka 和 RocketMQ ,但是由于它基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。但是也因为 RabbitMQ 基于 erlang 开发,所以国内很少有公司有实力做erlang源码级别的研究和定制。如果业务场景对并发量要求不是太高(十万级、百万级),那这四种消息队列中,RabbitMQ 一定是你的首选。
kafka
特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms 级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展。同时 kafka 最好是支撑较少的 topic 数量即可,保证其超高吞吐量。kafka 唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略,这个特性天然适合大数据实时计算以及日志收集。
二.RabbitMQ
RabbitMQ是一个瑞典通讯公司开发的软件,基于 erlang 语言,由于最初被当做通信软件设计和使用,所以它的并发能力很强,性能极其好,延时很低。非常适合用在对并发量要求不是太高的业务场合。
RabbitMQ有六种工作模式,下面我会一一介绍:
1.简单队列
RabbitMQ是一个消息代理。它的工作就是接收和转发消息。你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处。在这个比喻中,RabbitMQ就扮演着邮箱、邮局以及邮递员的角色。
RabbitMQ和邮局的主要区别在于,它不是处理纸张,而是接收、存储和发送消息(message)这种二进制数据。
下图中,“P”代表生产者,“C”代表消费者,中间的红色盒子代表为消费者保留的消息缓冲区,也就是消息队列。这是一个最简单的RabbitMQ的例子
2.工作队列
工作队列(又称:任务队列——Task Queues)是为了避免等待一些占用大量资源、时间的操作。当把任务(Task)当作消息发送到队列中,一个运行在后台的工作者(worker)进程就会取出任务然后处理。当运行多个工作者(workers),任务就会在它们之间共享,这几个工作者会一起处理这些任务。
3.发布/订阅
相比于之前的工作队列队列模式,发布/订阅多了一个交换机(exchange)。
发布者(producer)只需要把消息发送给一个交换机。交换机一边从发布者方接收消息,一边把消息推送到队列。交换机必须知道如何处理它接收到的消息,是应该推送到指定的队列还是是多个队列,或者是直接忽略消息。这些规则是通过交换机类型(exchange type)来定义的。
交换器和队列之间的联系我们称之为绑定(binding)。如下图所示:
发布/订阅使用的交换机的类型是扇型交换机(fanout exchange),扇型交换机会把消息转发给所有队列。
发布/订阅模式下,消费者不用在将消息一个一个的发送到所有队列中,消费者只需要将消息发送给交换机,交换机就会将消息自动转发给所有生产者。
4.路由
交换机是由很多种类型的,扇型交换机(fanout exchange)没有足够的灵活性 —— 它能做的仅仅是广播,将消息发给所有队列。直连交换机(direct exchange)有路由的功能 —— 交换机将会对绑定键(binding key)和路由键(routing key)进行精确匹配,从而确定消息该分发到哪个队列。
5.主题交换机
主题交换机(topic exchange)相比于扇型交换机和直连交换机来说,多了一个规则匹配的功能,通过“#”和“.”两个符号组成的规则来匹配路由键(routing key),“#”可以匹配多个单词,“.”只能匹配一个单词。
如下图所示,三个绑定键(binding key)的匹配规则分别是“*.orange.*”
,“*.*.rabbit ”
和 “lazy.#”
,则quick.orange.rabbit
会被发送到C2,lazy.orange.elephant
会被发送给C1,关于匹配规则的更详细的介绍,可以看这篇文章:RabbitMQ主题交换机,这篇文章是对RabbitMQ官网内容的翻译
主题交换机是很强大的,它可以表现出跟其他交换机类似的行为,当一个队列的绑定键为 “#”(井号) 的时候,这个队列将会无视消息的路由键,接收所有的消息。当 * (星号) 和 # (井号) 这两个特殊字符都未在绑定键中出现的时候,此时主题交换机就拥有的直连交换机的行为。
6.远程调用过程RPC
现在遇到一个需求,将一个函数运行在远程计算机上并且等待从那儿获取结果,这种模式通常被称为远程过程调用(Remote Procedure Call)或者RPC,处理这种场景以上的例子就不合适了。
这时就需要用到RabbitMQ的RPC模式了,在RabbitMQ的RPC模式中,RabbitMQ为每个客户端只建立一个独立的回调队列。这就带来一个问题,当此队列接收到一个响应的时候它无法辨别出这个响应是属于哪个请求的。correlation_id 就是为了解决这个问题而来的。我们给每个请求设置一个独一无二的值。稍后,当我们从回调队列中接收到一个消息的时候,我们就可以查看这条属性从而将响应和请求匹配起来。如果我们接手到的消息的correlation_id是未知的,那就直接销毁掉它,因为它不属于我们的任何一条请求。
来源:CSDN
作者:CycloneKid-blogs
链接:https://blog.csdn.net/eagleuniversityeye/article/details/103644891