RabbitMQ系列教程一:消息中间件的诸侯征战史,


什么是消息中间件?

消息中间件属于分布式系统中的一个子系统,关注于数据的发送和接收,利用高效可靠的消息传递机制对分布式系统中的其余各个子系统经进行集成

消息中间件的使用场景

1.异步处理非核心流程异步化,提高系统响应性能

原来用户注册一下可能得依次写数据库,发送邮件和短信后,才能提示用户注册成功

现在只要写数据库,写消息队列后就直接提示用户注册成功,发送邮件和短信是异步处理,提高了响应速度

2.应用解耦

系统不是强耦合,消息接受者可以随意增加,而不需要修改消息发送者的代码。消息发送者的成功不依赖消息接受者

rpc实现


消息队列实现

如果库存系统出了问题,用户就不能正常下单,这是不合理的。可以通过消息队列来解耦。

当有新的系统如广告系统对用户的订单也感兴趣的时候,只需要从消息队列中拿消息即可,订单系统完全不用改变

3.流量削峰

当上下游系统处理能力存在差距的时候,可以用消息队列进行缓冲

在这里插入图片描述

当有秒杀业务时,一下有大量请求涌入时,很可能造成系统瘫痪,此时可以用消息队列缓冲一下

4.日志处理

将消息队列用在日志处理中,比如Kafka可以用来解决大量日志传输的问题

5.消息通讯

消息队列一般都内置了高效的通信机制,因此也可以用于单纯的消息通讯,比如实现点对点消息队列或者聊天室等

消息中间件编年史

初见曙光

1.消息中间件其实诞生的很早,在互联网应用还是一片荒芜的年代,有个在美国的印度哥们Vivek Ranadive就设想了一种通用软件总线,采用发布订阅的模式,像主板上的总线一样供其他相应程序接入。他创办了一家公司Teknekron,实现了世界上第一个消息中间件The Information Bus(TIB)

各自为战

2.TIB受到了企业的欢迎,Teknekron的业务发展引起了当时最牛气的IT公司IBM的注意,于是他们也开始研发了自己消息队列软件,于是才有了后来的wesphere mq,微软也陆续加入了战团。由于商业壁垒,商业MQ供应商想要解决应用应用互通的问题,而不是去创建标准来实现不同MQ产品间的互通,或者允许应用程序更改MQ平台

劫制天下

3.为了打破这个壁垒,同时为了能够让消息在各个消息队列平台间互融互通, JMS (Java Message Service) 应运而生 。JMS 试图通过提供公共 Java API 的方式,隐藏单独 MQ 产品供应 商提供的实际接口,从而跨越了壁垒,以及解决了互通问题。从技术上讲, Java 应用程序只需 针对 JMS API 编程,选择合适的 MQ 驱动即可, JMS 会打理好其他部分 。ActiveMQ 就是 JMS 的 一种实现 。不过尝试使用单独标准化接口来胶合众多不同的接口,最终会暴露出问题,使得 应用程序变得更加脆弱 。所以急需一种新的消息通信标准化方案 。

一统江湖

4.在 2006 年 6 月,由 Cisco 、 Redhat 、iMatix 等联合制定了 AMQP 的公开标准,由此 AMQP 登上了历史的舞台 。它是应用层协议的一个开放标准,以解决众多消息中间件的需求和拓扑结 构问题 。它为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受 产品、开发语言等条件的限制 。

合久必分

5.LinkedIn在实现消息队列的时候觉得AMQP规范并不适合自己,所以Kafka并不支持AMQP协议。RocketMQ在实现上借鉴了Kakfa的思想,所以也不支持AMQP协议,并且你会发现在Kafka和RocketMQ中都有类似Topic和Consumer Group的概念,而这些概念在AMQP协议中是不存在的

如何选择消息中间件

消息模型

如果让你设计一个消息队列?你会怎么实现呢?

可能你立马就会想到用队列,一边放,一边取。这其实就是消息队列常见的一种消息模型,队列模型

所以一个简单的消息队列用Redis中的List就能实现。当然Redis5.0版本之后针对消息队列这种场景专门设计了一个数据结构Streams。

队列模型有哪些缺点呢?

如果将一类消息发送给不同的消费者,每个消费者都要接收全量的消息,此时就很不方便。因为你要将相同的消息发送到不同的队列,多一个消费者就得多发一份队列。这样生产者必须知道有多少个消费者,不利于解耦。

那么该如何解决这个问题呢?

想想RabbitMQ的结构图

RabbitMQ并不是直接把消息发送到队列中的,而是发送到Exchange中,Exchange和Queue进行关联,消息由Exchange根据规则发送到对应的队列。这样生产者和消费者完成了解耦。

还有哪种方式能解决这种多消费者的问题呢?

答对了,就是发布订阅模型

RocketMQ和Kafka都是基于发布订阅模型实现的,RocketMQ的消息模型图如下

生产者是发布者,消费者是订阅者,消息是主题

为了提高消费的并行度,一类消息会被分发到多个队列中,在RocketMQ中叫Queue,在Kafka中叫做Partition(分区),都是类似的概念。

AMQP协议详解

前面说到消息中间件有2种协议,JMS和AMQP。JMS你可以类比为JDBC,搞了一套接口让不同厂商来实现这个接口,但是这个协议设计的确实不够优雅,因此就不介绍这个协议了,除非你用ActiveMQ,不然学了真没啥用。详细说一下AMQP协议,毕竟现在用RabbitMQ的公司还是很多的,要想学好RabbitMQ,AMQP协议是必须要清楚的。

AMQP协议模型

上图是AMQP协议中一个消息的流转过程,画的的很清楚,不详细介绍了。

AMQP核心概念介绍一些AMQP协议常见的概念。

概念解释

概念 解释
Server 又称Broker,接受客户端的连接,实现AMQP实体服务
Connection 一个网络连接,比如TCP/IP套接字连接
Channel 多路复用连接中的一条独立的双向数据流通道。为会话提供物理传输介质
Message 消息,服务器和应用程序之间传送的数据,由Properties和Body组成。Properties可以对消息进行修饰,比如消息的优先级,延迟等高级特性,Body则就是消息体内容
Virtual Host 虚拟地址,用于进行逻辑隔离,最上层的消息路由。一个Virtual Host里面可以有若干个Exchange和Queue,同一个Virtual Host里面不能有相同名称的Exchange或Queue
Binding 消息队列和交换器之间的关联
Routing Key 一个消息头,交换器可以用这个消息头决定如何路由某条消息
Message Queue 消息队列,用来保存消息直到发送给消费者

如果有用过ActiveMQ和RabbitMQ,对上面的名词一定不会陌生。后面一篇文章就结合RabbitMQ来阐述上面的概念。

本文转载自微信公众号「Java识堂」,可以通过以下二维码关注。转载本文请联系Java识堂公众号。

相关内容