介绍
RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue)协议的开源实现。RabbitMQ整体上是一个生产者和消费者模型,主要负责接收、存储和转发消息。是当前最主流的消息中间件之一。
RabbitMQ的整体模型架构如下图:
生产者和消费者
生产者
生产者创建消息,然后发布到RabbitMQ中。消息包括(消息体和标签),RabbitMQ会根据标签把消息发送给感兴趣的消费者。
消费者
消费者连接到RabbitMQ服务器,并订阅队列,,消费者只会消费消息体,在消息路由的时候,消息的标签会丢弃,所以标签是不会存入队列中的。
Broker 消息中间件的服务节点
可以看成一个RabbitMQ服务结点或实例,消息队列服务器实体。
生产者将消息存入RabbitMQ Broker, 以及消费者从Broker中消费数据
队列
队列是RabbitMQ的内部对象,用于存储消息,RabbitMQ中消息都只能存储在队列中。
多个消费者可以订阅同一个队列,这个队列的消息会被平摊,给多个消费者处理,而不是每个消费者都接收所有消息并处理
交换器、路由键、绑定
Exchange(交换器)
真实情况上,生产者是不会直接把消息投递到队列,而是生产者将消息发送到交换器Exchange,由交换器将消息路由到一个或多个队列,如果路由不到,可能会返回给生产者,也可能直接丢弃。
RoutingKey(路由键)
生产者将消息发送给交换器的时候,会指定一个路由键,用老指定这个消息的路由规则,也就是路由键来决定消息的路由规则
Binding (绑定)
绑定,它的作用是把exchange和queue按照路由规则binding起来。
交换器相当于投递包裹的邮箱,RoutingKey相当于填写在包裹上的地址,BingingKey相当于包裹的目的地,两个地址匹配包裹才会被投递到目的地,否则会可能被丢弃或返回原主人
交换器类型
RabbitMQ常用交换器类型有
直连交换机:Direct exchange
扇形交换机:Fanout exchange
主题交换机:Topic exchange
首部交换机:Headers exchange
fanout
它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列
direct
它会把消息路由到那些BindingKey和RoutingKey完全匹配的队列
topic
它也是会把消息路由到那些BindingKey和RoutingKey相匹配的队列,但匹配规则有些不同
交换机和队列的binding_key需要采用*.#.*…的格式,每个部分用.分开
- *表示一个单词
- #表示任意数量(零个或多个)单词。
假设有一条消息的routing_key为fast.rabbit.white,那么带有这样binding_key的几个队列都会接收这条消息:
- fast…
- …white
- fast.#
- ……
headers
它不依赖路由键的匹配来路由消息,而是根据发送的消息内容中的headers属性进行匹配
RabbitMQ运转流程
生产者发送消息的时候:
- 生产者连接到RabbitMQ Broker,建立一个连接,开启一个信道
- 生产者声明一个交换器,并设置相关属性,比如交换器类型、是否持久化等
- 生产者声明一个队列并设置相关属性,比如是否排它,是否持久化,是否自动删除等
- 生产者通过路由键将交换器和队列绑定起来
- 生产者发送消息到RabbitMQ Broker,其中包含路由键、交换器等信息
- 相应的交换器会根据接收到的路由键查找相匹配的队列
- 如果找到,则将从生产者发送过来的消息存入相应的队列
- 如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者
- 关闭信道
- 关闭连接
消费者接收信息的过程:
- 消费者连接到RabbitMQ Broker,建立一个连接,开启一个信道
- 消费者向RabbitMQ Broker请求消费相应队列中的消息,可能会设置相应的回调函数,以及做一些准备工作
- 等待RabbitMQ Broker回应并投递相应队列的消息,消费者接收消息
- 消费者确定接收到的消息
- RabbitMQ 从队列中删除相应已经被确定的消息
- 关闭信道
- 关闭连接
Connection与Channel概念
1、 Connection:实际就是一条TCP连接,TCP一旦建立起来,客户端紧接着可以创建AMQP信道。
2、 Channel:每个Channel都有唯一的ID,都是建立在Connection上的虚拟连接,RabbitMQ处理每条AMQP指令都是通过信道完成的
3、单TCP复用连接与多信道的优势
- 为什么TCP连接只有一条,而每个生产者都会创建一条唯一的信道呢?想象下,实际情况,会有很多的生产者生产消息,多个消费者消费消息,那么就不得不创建多个线程,建立多个TCP连接。多个TCP连接的建立必然会对操作系统性能消耗较高,也不方便管理。从而选择一种类似于NIO(非阻塞I/O, Non-blocking I/O)技术是很有必要的,多信道的在TCP基础上的建立就是这么实现的。
- 每个线程都有自己的一个信道,复用了Connection的TCP连接,信道之间相互独立,相互保持神秘,节约TCP连接资源,当然本身信道的流量很大的话,也可以创建多个适当的Connection的TCP连接,需要根据具体业务情况制定。