RabbitMQ原理讲解

我们来看RabbitMQ的原理介绍,现在大家看到的这个图呢,其实就是通过图形方式,表达了RabbitMQ的

原理结构图,先不着急看第二个图,先来看第一个,其实这个图介绍了RabbitMQ一个消息的提供者发送消息,

直到消费者接收消息他的消息在RabbitMQ当中,是怎么处理的,这里会有一些常见的MQ当中的介绍,在这里主要

讲的是这些组件的信息

RabbitMQ原理讲解_第1张图片

我把表格里常见的组件,整理到一个表格当中,并且加了说明,我们来看一下,第一个Message消息,

那么什么是消息呢,其实就是从生产者,发送的信息,到接收者锁接收到的数据,我们称之为消息,其实

消息的构成呢,就是由一个字符串的二进制的,表现形式来构成的,底层其实都是二进制的,我们来看一下,

消息是不具名的,也就是消息它是不具备名称的,它是由消息头和消息体组成的,这个非常重要,比如我们要把

一个HelloWorld,从Provider提供到发送到Consumer,过程当中,其实消息是包含头和体两个部分组成的,然后我们

看一下,消息体是不透明的,消息头是由一系列可选的属性组成,消息头是很重要的,消息头里包括了什么呢,比如

路由件,还有相对于其他消息的优先权,还有指出消息可能持久性的一些设置,那么我们可以根据自己的需求,对消息

头的属性,来做一些设置,来决定这个消息是什么样的消息,是否要做持久性的操作,他的路由键是什么,消息头加上我们

具体的消息,其实就构成一个完整的消息,我们再来看第二个,Publisher,这个指的是什么呢,消息的生产者,就是这一块,

Provider,也是向交换器发布消息的客户端应用程序,这块就不用多说了,然后Consumer,Comsumer是消息的接收者,表示

从一个消息队列中,取得客户端的应用程序,这个也不用多说了,然后我们来看一下Exchange,Exchange是什么呢,这个是非常

重要的,它是一个交换器,交换器是用来接收生产者发送的消息,并将这些信息路由给服务器中的队列,然后他有三种常见的

交换类型,一个是direct,一个是fanout,还有一个是topic,这三种交换方式,决定你的消息是,所以他是一个交换器,也就是说,

我们现在发送一个消息,其实并不是直接进入到我们的Queue当中,并不是直接进入到队列当中,至于你这个消息,要进入到

哪个队列当中,其实是由交换器来决定的,现在我们通过管理页面来看一下,这是我们MQ的一个管理页面

59.110.158.145:15672

在这里是不是也有一个交换器,你看现在交换器有这么些,现在我们用的是AMQP default的交换器,这里面没有信息,

没有信息产生的原因是什么,是我们现在的服务已经停止了,程序没有停止,一直使用队列,

那么我们是可以看到的,那我们就做一个服务让他一直发送消息,

我们只要写一个死循环,我们让他休眠一下,每一秒发送一下,这个时候我们可以看到消息一直在发送,我们回到管理界面一下,现在我们

可以看出来了,交换器里已经有数据流产生了,那么其实交换器呢,是我们讲消息中间件最重点的部分,我们会讲三种交换器的类型,

我们先知道他就可以了,我们只要知道他什么呢,我们在使用消息中间件的时候,或者使用RabbitMQ的时候,他的消息的发送并不是直接

进入到队列里,而是经过交换器,来决定发送到哪个队列当中,其实这里还有一个非常重要的一个点,就是关于路由键的问题,一会咱们

再说,咱们再往下看,Binding绑定,这个绑定指的是什么意思呢,由于消息队列和交换器之间的关联,一个绑定就是基于路由键将交换器

和消息队列连接起来的路由规则,我们一个交换器,要想把消息发送到队列当中,那首先先要知道队列,所以交换器和队列之间,肯定要

做一个绑定的处理,那么绑定根据什么区绑定呢,这里说到了,其实根据的就是一个路由键,也就是说,在我们发送消息的时候,如果消息的

头信息当中,他头当中的属性,路由键相同,交换器就会将这个信息,发送到当前这个队列当中,所以说交换器,跟我们队列之间的对应关系,

是通过绑定来完成的,那么通过什么来绑定的呢,其实就是通过路由键来绑定的,我们再来看这个Queue,消息队列,

这个大家已经写过一个案例了,应该知道了,其实所谓的消息队列呢,就是用来保存消息直接发送给消费者,

这样的一个信息,它是消息的一个容器,也是消息的一个终点,

一个消息可以投入到一个或者多个队列当中,消息一直在队列里,等待消费者连接到这个队列将其取走,就是我们现在看到的这个Queue,

我们在管理页面其实也能看到,这个就是看消息队列的,我们只有一个队列,hello-queue,现在有数据的产生,因为我们的程序一直在运行,

然后我们再看路由键,路由键是什么呢,RabbitMQ决定消息该投递到哪个队列的一个规则,队列通过路由键绑定到交换器,消息发送到MQ

服务器时,消息将拥有一个路由键,即便是空的,RabbitMQ也会将其和绑定使用的路由键进行匹配,也就是说,即便你消息的头是空的,

他也会去和交换器跟队列所绑定的路由键,做匹配,所以只要我们消息想要放到队列里,必定会经过交换器当中的路由键来做匹配,

如果相匹配,就会将消息投递到该队列,如果消息并没有设置路由键,那怎么办呢,那就不匹配呗,如果不匹配,消息就将会进入到黑洞,

消息在一个独立的队列当中存储,在老版本的RabbitMQ当中,这个消息就直接丢弃了,直接就不要了,但是新版本的这个里面呢,

会用一个单独的空间来存储的,咱们再来看Connection,Connection指的是什么呢,链接,这个连接指的是什么呢,就是我现在的

信息,在我的Rabbit容器里存着呢,那我要把这个信息交给接收者,那我的服务端,肯定要和Consumer建立一个连接,那么这个建立

连接的过程,这个连接就叫Connection,应该很好理解,然后咱们再来看信道,我们先看这个图,一个Connection当中会包含多个信道的,

我们来看一下信道的解释,Channel中文也叫信道,是TCP里的虚拟连接,例如电缆相当于TCP,信道就是一个独立的光纤束,一条TCP

连接上,建立多条信道是没有问题的,什么意思呢,其实就是在一个连接当中,可以开辟多个通信的通道,才能称之为信道,那为什么没有

直接使用TCP进行通信了,咱们一会会讲到,现在你只要知道,这个信道指的就是,在一个TPC连接当中,开辟了多条通信的通道,

TCP一旦打开,就会创建AMQP的通道,无论是发布消息,接收消息,订阅队列,这些动作都是通过信道完成的,咱们再来看虚拟主机,

虚拟主机是什么意思呢,表示一批交换器,消息队列和相关的对象,虚拟主机是共享相同的身份认证和加密环境的独立服务器,

每个vhost本质上就是一个mini版的RabbiMQ服务器,拥有自己的队列,交换器,绑定和权限机制,vhost是AMQP概念的基础,必须在

连接时指定,rabbitmq默认的名称是/,我们来看,这个一个就是一个虚拟机,一个虚拟机就包含了一个rabbitMQ通信的机制,像

交换机,还有队列,都是在一个虚拟机里来完成的,其实你要理解虚拟机到底是什么,他有点像什么呢,有点像MYSQL数据库里的那个库,

库跟库是隔离的,那么其实在RabbitMQ当中,虚拟机和虚拟机之间也是隔离的,库跟库之间的访问权限,是不一样的,那么对于虚拟机来讲呢,

也是这样的,每个虚拟机都是独立的,每个虚拟机当中所使用的用户,关于权限这一块,也是针对虚拟机来设置的,他不能够跨虚拟机,

那么在一个RabbitMQ当中,我们也可以添加多个虚拟机,我们在MYSQL当中也可以建立多个库,是一样的,我们通过管理界面就可以完成,

在管理界面就可以完成,在admin这,然后这里有一个虚拟机

http://59.110.158.145:15672/#/users

http://59.110.158.145:15672/#/vhosts

然后在这里可以加一个虚拟机,可以给虚拟机起个名的,因为一个用户名只可以用于当前这个虚拟机,然后角色是通过虚拟机来分配的,

这个应该也不难理解,最后一个,其实最后一个我们来看一下,Broker指的是什么意思呢

RabbitMQ原理讲解_第2张图片

一个Rabbit的实体就称之为Broker,那么我们通过表格里的内容,以及对RabbitMQ关键的组件的介绍,重点是哪儿呢,

交换器和队列的关系,咱们之前说过交换器,建立在发送消息和队列之间的交换规则,他决定了将消息放在哪个队列当中,

并且根据你的路由键来决定的,哪个消息建在哪个队列,然后我们来看,交换器是通过路由键和队列绑定在一起的,如果消息

拥有的路由键跟队列和交换器的路由键匹配,那么消息就会路由到该绑定的队列当中,也就是说,消息到队列的过程中,

消息首先会经过交换器,接下来消息通过路由键,匹配分发消息到具体的队列当中,路由键可以理解为匹配的规则,其实我们在

学RabbitMQ的时候,重点就是这个交换器,所以我们接下来也会重点来讲解这个交换器,然后再来看关键的几点,RabbitMQ为什么

需要信道,为什么不是TCP直接通信,这一块非常重要,为什么RabbitMQ不是直接通过TCP连接,直接跟消费者进行消息的传递,

而是建立连接以后,在连接当中,多个信道跟消费者进行消息的传递呢,原因在这也给大家写出来了,一共三点原因,第一个TCP的

创建和消费的开销特别大,我们知道TCP的创建是需要三次握手,销毁的时候是需要四次分手的,所以正因为他有这么多次握手,

有这么多次分手,其实就导致TCP的创建和消费开销就特别大,这个开销大性能肯定会受到影响,第二个我们再来看,如果不用信道,

那应用程序会以TCP连接到Rabbit,高峰时成千上万条连接,会造成资源巨大的浪费,就是来一个连接,去创建一个TCP,来一个连接我就

去创建TCP,那你想想资源浪费的多么严重,然后用完之后还得把它销毁掉,销毁的时候还需要四次分手,创建的时候还需要三次握手,

你想想这个性能,随着我们的请求量越来越多,性能所遇到的瓶颈也会越来越大,还有关键的一点是什么呢,操作系统每秒处理TCP连接数

是有限的,并不是一秒钟可以去创建无限个连接的,不是这样的,操作系统对于每秒处理TCP的数量是有一个峰值的,当你达到这个峰值的

时候,你就无法建立连接了,所以必定造成性能的一个瓶颈,这也是为什么RabbitMQ,他并不是直接使用TCP,跟我们的Consumer进行直接的

通信,再来看,信道的原理,它是一个线程一个信道,它是运行在连接当中的,多条线程就是多个通道,通用一条TCP连接,一条TCP连接可以

容纳无限的信道,即使成千上万的请求也不会成为性能的瓶颈,这个是什么意思呢,不管你有多少个消息,我只要和Consumer

建立一个Connection连接,然后我所有的消息,都可以通过不同的信道来连接,其实这就很好的解决了什么呢,

解决了TCP链接慢,和每秒处理TCP链接有限制,

这样的一个问题,其实这个技术要找到一个比喻去比喻一下,也是可以找到相关的技术的,就是线程和进程的关系,比如我们每次运行一个程序,

都是以一个进程来运行,那你想一想,这将是一个怎样的现象,如果了解Servlet之前的技术,每次请求在操作系统当中,都是开辟一个进程

来处理这个请求,后来发现当请求上来以后,这个处理请求的Servlet,在创建进程的时候,是比较耗时的,第二个是什么呢,造成一个资源

浪费,因为一个请求来了,要创建一个进程,进程的开辟,它会占用你的不小的内存空间,后来又做了一个池,把一些servlet的进程,

放到池里去初始化,加入池去解决这个问题,也没有起到一个治本的问题,治标不治本的,直到Servlet诞生,他采用的是单进程多线程的

方式,彻底解决这个问题,其实这个跟我们的RabbitMQ当中为什么不用TCP,而是使用的TCP的通道来解决这个原理是一模一样的,

我们主要是讲解RabbitMQ的一个原理图,下面我们主要讲交换器的交换规则,交换器类型的使用,这个是我们学习中间件非常重要的

一个知识点

RabbitMQ原理讲解_第3张图片

 

你可能感兴趣的:(RabbitMQ原理讲解)