一、学习指南
Hello小伙伴们大家好。那么从今天开始我们就正式的进入这个消息中间件课程第一大块内容,也就是说关于RabbitMQ的实战的学习了。当然第二大块就是Kafka相关内容了,之前在课程最开始的导航,老师也说过,我们整个课程就围绕着两个消息中间件,一个就是RabbitMQ第二个就是我们的Kafka。 RabbitMQ我们要做什么?就是把它一些基础包括可靠性投递都全面的去讲解,包括跟springboot的整合,然后最终写了一个我们对应的想要自己去封装一个RabbitMQ的基础组件,让大家提升一下编码能力,这也是核心。 首先我们看一下课程的目录,对于RabbitMQ它里边有一些基础的概念,这些基础的概念如果小伙伴们学过的话,你就去复习一下。如果没学过你就要提前预习。比如说amqp的核心概念,像exchange交换交换机,然后quene队列等等这一些概念,包括whitchhost虚拟主机等等,这些你都要自己学习。如果已经有基础的,你复习一下就可以了。当然老师会给你发一些相关的资料文档,采用这种文图的学习的方式,让小伙伴快速的去预习去学习。
因为这些都是比较基础的,包括你看后面RabbitMQ一些极速安装跟入门,只需要你在Linux7上安装一个RabbitMQ对应的版本,然后写一个简单的hello word,能够收发消息就可以了。
包括RabbitMQ的核心API这些老师都会提供一些文图的资料,不需要担心以及RabbitMQ的一些高级特性。比如说我们的TTL消息,死循环队列,包括像confirm模式、 return模式,以及 oqs、限流等等,这些都是RabbitMQ的一些高级特性。我们都是采用文图的方式。
再往下看,接下来这个就比较关键了,就是RabbitMQ的集群架构操作。按照老师的操作自己一步一步操作就可以了。这样的话也是锻炼你的一个集群搭建的怎么说硬性的能力。后面如果对于集群搭建有什么疑问,都可以在群里或者是跟老师直接沟通,也算是一个小的作业,对于RabbitMQ进行搭建,我们在这里肯定是对镜像进行搭建。
再往下看,这个就比较关键了,就是与springboot怎么去整合实战?对于springboot的我们大多数小伙伴应该都非常的了解,我们在这里是用的是2.1.5 Release版本的springboot,跟RabbitMQ他的生产以及消费者怎么去发消息收消息,以及怎么去写我们的这种确认消息,包括消费端怎么去做手工的act,实际工作中应该怎么去用,结合着控制台应该怎么去使用,怎么去看,怎么去理解它,这个非常重要。
所以说这个东西我们是真正的去通过课程从头到尾从0~1跟大家去讲清楚,希望帮助小伙伴们在实际的工作中能够更好的去对此次springboot整合RabbitMQ作为一个基础。接下来就是我们整个第一大块内容就是RabbitMQ这个消息中间件里面最重要的内容了。就是说我们想要把RabbitMQ封装成一个基础组件,比如说它的可靠性投递,后面我会详细的讲。
什么是可靠性投递? 比如它的一些delay消息、顺序消息,包括延迟消息等等这些我们都会从0~1的带着小伙伴们一点一点去编码来做一个这样的一个基础的组件,只有这样的话,你才能够提升你的硬编码能力。到时候老师会结合着一些架构的设计,思想,设计模式等等融会贯通到技术资源当中,希望小伙伴跟我一起共同的去学好这第一块内容。
二、哪些互联网大厂在使用RabbitMQ,为什么
这节课我们来一起认识一下RabbitMQ,首先RabbitMQ它是一个开源的消息代理和队列服务器,也就是说它是一个开源的消息中间件,然后它可以用来通过普通的协议,在完全不同的应用之间实现一个数据的共享。这句话的含义无非就是说RabbitMQ可以实现这种跨平台跨语言的机制,比如说我们的前端使用的是Java去编写的,然后调用Java的API去把消息进行一个投递,发送到我们的RabbitMQ服务器上,然后我们的后端可以采用其他的语言,比如说Python、 Ruby,包括PHP等等其他的语言,都可以去监听这个消息,然后进行一个数据的消费,这都是可以的。
RabbitMQ它使用的开发语言是Erlang, 并没有选择我们非常熟悉的Java语言去编写的,然后并且RabbitMQ它是基于AMQP协议的。
Ok,那么通过这一简简单单的一句话的描述,我相信咱们同学肯定有很多疑惑,或者说很多问题,对不对?比如说RabbitMQ它的成熟度怎么样,它业界使用度怎么样?是不是非常的广泛?包括RabbitMQ它有哪些特性特点,对吧?还有RabbitMQ就为什么是使用Erlang语言去编写的,是不是?包括什么是amqp协议,是不是AMQP协议里边它具体的规范就是什么对吧?这些我相信咱们同学都是非常关心和关注的,那么在后续的课程中,我们会一一的给大家进行一个讲解。
那么今天我们先聊第一个小的问题,就是说哪些大厂在用RabbitMQ,为什么去用它选择的理由是什么?是不是它有哪些优点?Ok。首先据我了解,比如说像滴滴、美团、头条去哪儿艺龙,现在可能叫艺龙的,携程它已经合并了,这些互联网大厂都会采用RabbitMQ作为它底层的消息流转消息通讯的一个基础组件,使用这个软件,为什么?
我们来看一看,首先第一个原因就是说他的性能非常的优秀,本来开源就不用说了对吧?然后它可以提供一个高稳定性的保障。
第二点它可以提供可靠性的消息的投递,也就是说confirm模式,但我相信如果你有mq开发经验的,你肯定会被可靠性投递所困扰的,这个其实是一个mq非常关注的点。Ok然后以及它提供了一些返回模式,包括它还有一些其他的模式,在后续的过程中再一一跟咱们同学说,也就是说它的消息投递模式非常的丰富。
Ok接下来它还有一个优点就是说它与SpringAMQP整合非常的完美,其实提供了非常丰富的API,比如说我们spring对RabbitMQ的原生的 API进行了一次再封装,把它的功能变得更简单更易用,然后扩展性变得更强,提供了很多非常优秀的功能,包括池化等等一些概念。
接下来就是说RabbitMQ它的集群模式非常的丰富,聊到集群,我相信咱们同学肯定知道这个概念到底是什么意思,是不是?
并且这个RabbitMQ它支持表达式的配置,也就是说到底是我的集成策略到底采用什么样子的,我可以通过一个简简单单的命令就可以实现一个配置, HA模式其实就是一个高可用模式,并且它也支持这种镜像队列模型,这也是RabbitMQ大家都在使用的一种非常稳定的集群模式,后期我会重点去跟咱们同学讲解这种集群模型。
接下来它可以在保证数据不丢失的这么一个前提下,做到高可靠性可用性,并且它其实性能也非常的好。Ok,那么今天咱们就聊到这,主要是带着大家初步认识一下RabbitMQ,然后它的使用度到底怎么样?到底哪些大的规模的互联网公司在使用RabbitMQ以及为什么去使用,有哪些特点?在这里简单的跟咱们同学进行了一个分享。
三、RabbitMQ高性能的原因
那么这节课我们来聊一聊RabbitMQ它高性能的原因。首先我们来看一下RabbitMQ他为什么性能这么高,其实原因就是因为他使用的开发语言是Erlang语言而Erlang它其实广泛应用于交换机领域这种架构模式,都采用Erlang语言去做,原因是因为它Erlang语言进行数据交换,数据同步这个过程它的性能是非常的优秀的,这是其中的一点。
还有一点最关键的是为什么?其实取决于这个作者,那么在这里其实想跟咱们同学简单聊一聊,RabbitMQ它的开发的作者他在开发之前,他用Erlang语言去做了一个网络交换机的这么一个小程序,然后他惊奇的发现RabbitMQ就有一个非常牛逼的特点,什么特点呢?它有着语言生socket一样好的这么一个延迟效果。
接触过socket的同学,我相信对于socket是一个什么样的性能,大家肯定都非常的清楚。像我们耳熟能详的 rpc通信框架,比如说doubble它底层就是采用了netty,netty无非就是网络编程中高性能之王,性能非常的不错,它就无非就是一个 socket。
好了,那么基于这个特点,我们就有了一个充分的选择RabbitMQ的理由。
其实我们在选择mq的时候,主要有一个非常关键的考量目标,它消息入到我们mq节点上之后,它的延迟以及响应其实是非常至关重要的,任何一个架构的转型者或者是设计者都会考虑到这一点,就是说你 mq它到底延迟怎么样,吞吐量怎么样,性能怎么样,ok。这节课就跟大家简单分享了一下高性能的原因,核心就是它采用的语言叫做Erlang语言。
四、AMQP高级消息队列协议与模型
那么这节课我们来说一说什么是AMQP高级消息队列协议。首先我们来看一下这个单词。它的全称翻译过来就是说高级消息队列协议。
Ok这个概念我们来聊一聊。首先它是具有一个现代特性的二进制协议,也就是说它其实是一个基于二进制去做的这么一个协议,然后是一个提供了统一消息服务应用层标准的高级消息队列协议,通过这块咱们同学就知道,它就比较类似于我们的 Java的 GMS (Java message),是不是?它其实就是一个比较上层的这么一个规范,我们下面基于规范可以开发出各种各样的消息中间件,是不是?比如说amqp协议它是一个规范,它的下层可能有RabbitMQ,以后可能有其他的MQ,我们的Java的GMS也是一样的,是不是?它规范定出来可能遵循规范有ActiveMQ,如果大家有了解过ActiveMQ的话,应该知道消息中间件也是非常主流的一种消息中间件,但其实主要想跟大家说的就是什么,就是说amqp它其实就是一个规范,它里边定义了很多个相关的一些核心的概念,然后你再进行开发的时候,按照我这个概念去走就好了。
那么咱们来看一看规范的协议模型到底是一个什么样子的,我们看这个图左边这里边有个叫做publisher application,也就是说我们的生产者的应用服务,然后这里面有个箭头,就是说它要把具体的生产出来的消息扔到我们的server端,这个server指其实就是我们的RabbitMQ的节点了, ok。
然后这个节点里边具体有一些内容,比如说像我们里边这块有一个叫做Virtural hose的这么一个东西,这个叫做虚拟主机的概念,我们后续再去说,它其实就是一个比较上层的这么一个路由,并且它也是一个逻辑的概念,这个我们后续详细去讲就好了。
然后它在里边有一个叫做exchange的东西,这个是我们RabbitMQ也就是不仅仅是RabbitMQ了,更上一级别的就是说amqp协议的这么一个核心就是exchange叫做交换机,然后我们的生产者其实把消息直接投递到 server里面的什么位置,就是 exchange的这么一个位置。
当然他要经历这三个过程,第一过程就是说我把消息投递到哪个服务器上,比如说你得去建立连接,然后去设置一些地址等等,然后第二层是什么呢?
第二层你要投递到哪个virtual host上进行一个定义,然后接下来你要把你的消息投递到具体的哪一个exchange上,所以说它这个图画的层次感非常的强,让人一目了然,然后我们的生产者就就不用管其他事情了,mq本身它的作用就是用来解耦的,所以说我们下面这块有一个叫做consumer application,就是我们消费者的应用服务端,然后它只需要做什么事情呢?
他只需要去监听message Queue,也就是说只需要监听消息队列,这个队列里有一条消息,我就拿出来进行消费就好了。
那么其实核心的点就在于什么?就是说 Exchange跟 message Queue之间有没有什么关系能够关联上,如果说你关联不上的话,生产者投递到Exchange上,消费者却从 message Queue上去取数据,这个很显然不太合理对吧?所以说exchange跟Queue其实是有一个绑定的这么一个关系的。在我们后续的课程中再跟大家去详细的去介绍,我们先初步的有这么一个图形化的概念。
五、AMQP核心概念讲解
那么这节课我们来聊一聊amqp具体的核心概念。那么在咱们上几节课中简单介绍了一下amqp,它就是一个比较上层的协议,然后又领着咱们同学看了一下他的 amqp的一个整体架构图,是不是?这节课我们就来看一看具体核心概念它的规范都有哪些?
首先我们来看第一个就是server,这个就非常好理解了,那我们的RabbitMQ的服务器一般都叫做broker,它作用是干什么的?它用于接收client端的一个连接,实现我们的amqp实体服务,这是一个server概念。
接下来我们看一下collection建立连接,然后跟我们具体的broker进行一个网络的连接,我们的应用程序跟我们的broker要有一个连接, Ok然后再往下走。
channel这个概念非常的关键,也是非常特殊,China它叫网络信道,它说几乎所有的操作都是在channel上进行的,这是什么意思呢?
我们的数据读写都是要通过channel去做的,比如说你做一些消息的流转,你都得去用到 channel,包括你比如说对我们的 mq服务器做一些其他相关的管理性的操作,比如说像清空队列里的消息,删除某一个队列,删除一个exchange,包括添加用户等等都需要用到 channel,它是一个非常核心的概念。
客户端可以去建立多个channel,每一个channel的表示一个会话任务,这个概念就很好理解了,有点类似于像咱们的数据库里面的session,我们通过拿到connection,然后通过connection去创建session,在这里我们的RabbitMQ也是一样的,拿到连接之后也是去要创建channel的,这是一个非常关键的点,希望咱们同学仔细的去进行一个记忆。
接下来我们再继续走message,这个message就是一个消息,大家如果接触过一点点消息队列,那就对这个消息应该非常清楚的是吧?然后它就是用于我们的服务器与这个服务器之间应用与应用之间进行传递的这么一个实体数据,是不是,在我们的RabbitMQ里边,它的消息结构有两部分组成,这个其实是我非常想跟大家说的,因为每一种mq或者说每一种协议比较上层的,比如 GMS协议像amqp协议,他们的消息结构定义的都是不同的,我们的amqp定义的消息是什么?
它由两部分组成,一部分叫做properties,还有一部分叫做body。
Properties的意思,就是说可以对这个消息进行一些设置,比如说我想设置一下这个消息的优先级,是不是我想设置一下它的消息,让它延迟投递,它等一会再去把它发到队列,这都是可以去做的。body其实就是我们的实体内容,就是我们真实的发的数据是什么。
接下来我们往下去看核心概念,还有叫做virtual host, virtual host就比较厉害了,它的概念叫做虚拟主机。
如果说没有接触过RabbitMQ的同学,可能对这个概念就比较发懵,不知道它是一个什么概念。
在这里简单跟大家说,它主要就是进行一个逻辑的这么一个隔离,它是一个最上层的消息的路由,那一个 virtual host里边可以有若干个exchange和Queue,然后同一个 virtual host里边不能有相同名称的exchange和Queue,其实 virtual host的概念它是一个逻辑的概念,我们通过这段话知道了什么叫做逻辑的概念,咱们回想一下redis,大家都用过redis缓存,redis默认它有16个DB16个数据库,其实redis它就是一个逻辑的隔离的概念,比如说我们分配了16g的内存给redis,可能我们默认就是select0, select DB 0就是使用第0个数据库,你第0个数据库它就可以去占很多的这种内存,可以占十五六G是不是,甚至占满都可以了?
这是为什么?是因为它是一个逻辑的概念,它并不是一个物理的概念,是不是?我把数据库分成了16份,DB0=1g,DB2=1g,DB3=1g,以此类推,它不是这样的,它是一个逻辑的概念。
我们的RabbitMQ为什么要设置这么一个virtual host?其实它就是用来一个最上层的消息的路由,来划分具体的服务的,比如说以后你可能有多个应用服务在开发,是不是?我a服务我可以把消息都可以路由到 virtual host等于/a这么一个层次上,然后b服务可以把消息路由到第二个virtual host主机上,这个是可以的,这也是非常具有强烈的层次感,如果咱们同学可能还没有太理解virtual host,你可以看一看老师之前在讲amqp这种核心的这种流程图的时候,说的层次划分好了。
接下来我们继续往下走,exchange这个叫做交换机,它是用于接收消息的,它是可以根据消息的路由键转发消息到所绑定的队列,其实这句话就感觉比较绕口。
在这里简单来讲一下,就是说我们的生产者把消息直接就应该投递到exchange上,然后通过exchange去进行一个路由,路由到指定的队列,但是你的队列应该跟exchange有一个绑定的关系,这样也就说明了绑定的概念是不是,就是exchange和队列之间的一个虚拟连接,绑定中可以去包含路由Queue,就是他们两个建立一个绑定关系才可以,没有绑定关系,其实我们的生产者把消息投递出去了,我们就是没有队列去进行监听,没有队列进行消费,是这么一个事儿。
好了,这个绑定之后说可以包含路由 key又是一个什么概念?我们来看一看路由 key,这个路由 key就是一个路由规则,虚拟机可以用它来进行确定如何路由一个特定的消息,其实它就是用来做一个交换路由的这么一个事。
然后我们继续往下走,Queue这个Queue咱们同学肯定都理解了,是不是前面那几个可能像虚拟主机、绑定、Routing key我们单纯的从概念上可能大家不是那么特别明白,在我们后续的课程中会进行一个画图分析,然后包括代码的演练来帮助咱们同学去理解这些核心概念,但是Queue那就不需要这么麻烦了,他就是一个消息队列就用来保存消息,然后由消费者去监听之后进行一个处理就好了。
Ok这也是我们这一讲所主要讲的核心内容,就是mqp的核心概念,有这么几点,咱们同学先有一个大概的认知,然后以后在实际的编码的时候再跟咱们同学详细的去进行进行讲解。
六、RabbitMQ整体架构与消息流转
那么这节课我们来看一看,RabbitMQ整体的架构是一个什么样子?来,我们来看这张图,这张图其实是有左边和右边,还有中间三部分。首先左边蓝色的p表示的是 producer,也就是我们的消息的生产者,右边 c就表示我们的 consumer,消息的消费者。中间这一块就是我们的server端,也就是我们的RabbitMQ的broker。
通过这个概念其实就很显然很清晰的表述了我们RabbitMQ它整体的一个架构。
首先我们关注生产者把消息投递到了server端,具体投递到哪了,投递到了绿色的叉,它其实就是一个exchange,就是说交换机这么一个概念,然后交换机又怎么去做流转,他又把消息往下传递到了红色的叫做队列就是messageQueue。
其实它整体就是一个这样的简单的机制,我们的生产者只需要关注把消息投递到指定的exchange即可,我们的消费者也只需要监听指定的队列就可以了,通过这个图清晰地说明了生产者不需要关注,我要把消息投递到哪个队列,消费者也不需要关注他这个消息是从哪个exchange上来的,也就是说这两块完全没有说偶合的这么一个情况,他们之间又是怎么去流转,无非就是说exchange跟我们队列有一个绑定关系,通过这个上面有一个英文叫做exchange route and filter message,就是说它可以通过Exchange把消息进行一个过滤,进行一个路由到指定的队列上,然后我们的消费者去监听队列,然后接收消息进行消费就好了,这也是一个非常简简单的这么一个RabbitMQ的架构图。
好了,我们来看他消息流转图,这个就是我们的生产者就是publish application,它生产出来一个消息message,然后投递到我们的mq上,投递到mq的哪个位置就是 exchange,然后一个exchange其实可以绑定多个message queue的,也就是说exchange是给你绑定多个队列的,然后为什么我们看这个图这里面有三个队列,只有其中一个队列收到了这个消息,这个原理就是因为说我们的exchange其实是有一个路由策略的,这个路由就是routine key就是我们之前所讲到的概念,也就是说我们发消息的时候要指定两个非常关键的点或者说属性,第一个就是说你这个消息要发到哪个exchange上。
第二个就是说你发消息的时候,要带上路由的key就是routine key然后通过exchange跟队列建立一个绑定关系,通过你的路由kry把消息路由到指定的一个队列上,然后我们的consumer端就是消费端,然后去直接监听队列就好了,然后就可以进行消费了。