RabbitMQ-基本概念(一)
消息中间件的作用
息中间件的作用可以概括如下。
冗余(存储):有些情况下,处理数据的过程会失败。消息中间件可以把数据进行持久化直
到它们已经被完全处理,通过这一方式规避了数据丢失风险。在把一个消息从消息中间件中删
除之前,需要你的处理系统明确地指出该消息已经被处理完成,从而确保你的数据被安全地保
存直到你使用完毕。
扩展性:因为消息中间件解耦了应用的处理过程,所以提高消息入队和处理的效率是很容
易的,只要另外增加处理过程即可,不需要改变代码,也不需要调节参数。
削峰:在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常
见。如果以能处理这类峰值为标准而投入资源,无疑是巨大的浪费。使用消息中间件能够使关
键组件支撑突发访问压力,不会因为突发的超负荷请求而完全崩溃。
可恢复性:当系统一部分组件失效时,不会影响到整个系统。消息中间件降低了进程间的
耦合度,所以即使一个处理消息的进程挂掉,加入消息中间件中的消息仍然可以在系统恢复后
进行处理。
顺序保证:在大多数使用场景下,数据处理的顺序很重要,大部分消息中间件支持一定程
度上的顺序性。
缓冲:在任何重要的系统中,都会存在需要不同处理时间的元素。消息中间件通过一个缓
冲层来帮助任务最高效率地执行,写入消息中间件的处理会尽可能快速。该缓冲层有助于控制
和优化数据流经过系统的速度。
异步通信:在很多时候应用不想也不需要立即处理消息。消息中间件提供了异步处理机制,
允许应用把一些消息放入消息中间件中,但并不立即处理它,在之后需要的时候再慢慢处理。
RabbitMQ特点
Rabbit MQ的具体特点可以概括为以下几点。
1.可靠性:Rabbit MQ使用一些机制来保证可靠性, 如持久化、传输确认及发布确认等。
2.灵活的路由:在消息进入队列之前,通过交换器来路由消息。对于典型的路由功能,
Rabbit MQ已经提供了一些内置的交换器来实现。针对更复杂的路由功能, 可以将多个
交换器绑定在一起,也可以通过插件机制来实现自己的交换器。
3.扩展性:多个Rabbit MQ节点可以组成一个集群, 也可以根据实际业务情况动态地扩展
集群中节点。
4.高可用性:队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下队
列仍然可用。
5.多种协议:Rabbit MQ除了原生支持AM QP协议, 还支持STOMP、MQT T等多种消息
中间件协议。
6.多语言客户端:Rabbit MQ几乎支持所有常用语言, 比如Java、Python、Ruby、PHP、
C#、JavaScript等。
7.管理界面:Rabbit MQ提供了一个易用的用户界面, 使得用户可以监控和管理消息、集
群中的节点等。
8.插件机制:Rabbit MQ提供了许多插件,以实现从多方面进行扩展,当然也可以编写自
己的插件。
整体架构模型
RabbitMQ运转流程
生产者发送消息过程
(1)生产者连接到RabbitMQ Broker 建立连接(Conneciton),开启一个信道(Channel)
(2)生产者声明一个交换器,并设置相关属性,比如交换机类型、是否持久化等(详细内
容请参考3.2节)。
(3)生产者声明一个队列并设置相关属性,比如是否排他、是否持久化、是否自动删除等
(详细内容请参考3.2节)。
(4)生产者通过路由键将交换器和队列绑定起来(详细内容请参考3.2节)。
(5) 生产者发送消息至Rabbit MQ Broker, 其中包含路由键、交换器等信息
(6)相应的交换器根据接收到的路由键(RoutingKey)查找相匹配(BindingKey)的队列。
(7)如果找到,则将从生产者发送过来的消息存入相应的队列中。
(8)如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者
(9)关闭信道。
(10)关闭连接。
消费者接收消息的过程:
(1) 消费者连接到Rabbit MQ Broker, 建立一个连接(Connection) , 开启一个信道(Channel) 。
(2) 消费者向Rabbit MQ Broker请求消费相应队列中的消息, 可能会设置相应的回调函数,
以及做一些准备工作
(3) 等待Rabbit MQ Broker回应并投递相应队列中的消息, 消费者接收消息。
(4) 消费者确认(ack) 接收到的消息。
(5) Rabbit MQ从队列中删除相应已经被确认的消息。
(6)关闭信道。
Producer
消息生产者,生产者创建消息然后发布到RabbitM中,消息一般包含2个部分 消息体(payload)和标签 消息体就是带有业务逻辑结构的数据,消息标签用来表述这条消息,比如交换器名称和路由键
生产者将消息交给RabbitMQ rabbItMQ会根据标签将消息投递到对应的消费组
队列
RabbitMQ的内部对象,用于存储消息 rabbitMQ不支持广播消息,当多个消费者订阅同一个队列,则会平均分摊到对应的消费者
Consumer
消费者,消费组连接到RabbitMQ并订阅到队列上,当消费一条消息只会消费消息体 标签会被丢弃
Exchange
交换器,生产者将消息投递到exchange exchange将消息路由到一个或者多个队列 如果路由不到可以返回给生产者或者直接丢弃exchange含有4种类型
fanout:将所有发送到该交换器的消息路由到所有与该交换器绑定的队列中(不需要经过binding key 路由 所以最快)
direct:将消息路由到routing key和binding key完全匹配的队列中
topic:direct是完全匹配 topic则是模糊匹配 如有路由键 注:这里的模糊不是发送消息的routing_key模糊 而是exchange bindKey映射投递的模糊
投递路由键(routingKey)com.rabbitmq.client或者java.rabbitmq.demo:可以路由(bindingKey):*.rabbitmq.*
投递路由键(routingKey):com.rabbitmq.client或者com.hiddent.client可以路由(bindingKey)*.*.client
投递路由键(routingKey):com.rabbitmq.client或者com.hiddent.client com.hiddent.demo可以路由((bindingKey))com.#
.分割的算一个但是 *表示模糊一个单词 #表示多个单词
比如*.rabbitmq.* 表示[任意一个单词].rabbitmq.[任意一个单词] com.test.rabbitmq.com 是不能路由的 因为rabbtimq左边有2个单词 com和test
headers,
不依赖于路由键盘的匹配规则来路由消息 而是根据发送消息内容中的headers属性进行匹配,在绑定队列和交换器时指定一组键值对,发送消息会获取headers的来进行路由匹配 效率很低 基本不会使用
RoutingKey
路由键,生产者将消息发给交换器的时候一般会指定一个routingKey用来指定这个消息的路由规则, 交换机根据自身类型根据routingKey映射BindingKey将消息投递到BindingKey对应的队列
BindingKey
通过BidingKey将交换器与队列关联起来 交换器通过RoutingKey映射BindingKey知道路由到哪个队列上
复用Channel
信道是建立在Connection之上的虚拟连接,RabbitMq处理每条AMQP指令都是通过信道来完成的。
发送消息和消费消息都需要1.创建连接再根据连接创建channel 跟java nio模型一样,复用连接多个生成者和多个消费者复用一个连接,避免为每个生产者和消费者都创建一个连接
但是要注意channel并不是线程共享的 需要为每个线程创建一个channel 不能a线程创建了channel进行发送消息 然后又给b线程发消息 b线程应该另外创建channel
需要注意的是
1.多个信道复用一个连接,如果信道流量不是很大,可以避免重复建立多个TCP连接的开销。
2.如果遇到一个信道本身流量很大的时候,如果这个时候多个信道复用一个Conection就会产生性能瓶颈,进而使整体流量被限制了。这个时候就要开辟多个Conneciton,将这些信道均摊到每个Conneciton中