RabbitMQ
1、什么是消息中间件
消息队列中间件(MessageQueueMiddleware,简称为MQ)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。
1.1传递模式
1)点对点模式
基于队列,息生产者发送消息到队列,消息消费者从队列中接收消息,队列的存在使得消息的异步传输成为可能。
2)发布/订阅
定义了如何向一个内容节点发布和订阅消息,这个内容节点称为主题(topic),主题可以认为是消息传递的中介,消息发布者将消息发布到某个主题,而消息订阅者则从主题中订阅消息。主题使得消息的订阅者与消息的发布者互相保持独立,不需要进行接触即可保证消息的传递,发布/订阅模在消息的一对多广播时采用。
2、消息中间件的作用
- 解耦
应用程序之间通过消息进行通信,通信双方无需感知对方的存在,即使通信双方有一方突然挂了也不会影响自己的处理。
- 异步
消息生产者无需等待消费者处理结果,将处理过程由串行改为并行,缩短了程序的处理时间。
- 削峰
在面对大流量访问时,消息中间件成为消息的暂存地,使得消费方始终以某一速率对消息进行消费,将短时间内产生的大量请求分散到一个相对时间较长的调用链中,即消息被延缓执行。
3、基本概念
消息包含消息体和标签,消息体是消费方实际接收到的数据,标签这条消息的描述,如交换器和路由键
- Producer::生产者,投递消息的一方
生产者负责创建消息并投递到rabbitmq中。
- Consumer:消费者,就是接收消息的一方。
消费者连接到RabbitMQ服务器,并订阅到队列上。当消费者消费一条消息时,只是消费消息的消息体。消费者不知道生产者是谁。
- Broker:消息间件的服务节点。
可以看作一个RabbitMQ服务节点,或者RabbitMQ服务实例。多数情况下也可以将一个RabbitMQBroker看作一台RabbitMQ服务器。
消息队列的运转过程
- Queue:队列,存储消息的数据结构
RabbitMQ不支持队列层面的广消费。生产者生产消息井最终技递到队列中,消费者可以从队列中获取消息并消费。
多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin即轮询)多个消费者进行处理,而不是每个消费者都收到所有的消息井处理。
多消费者
- Exchange:交换器
产者将消息发送到Exchange(交换器,通常也可以用大写的"X"来表示),由交换器将消息路由到一个或者多个队列中。如果路由不到,或许会返回给生产者,或许直接丢弃。
- RoutingKey:路由键
生产者将消息发给交换器的时候,一般会指定一个RoutingKey,用来指定这个消息的路由规则,而这个RoutingKey需要与交换器类型和绑定键(BindingKey)联合使用才能最终生效。
- Binding::绑定。
RabbitMQ中通过绑定(Binding)将交换器与队列关联起来,在绑定的时候一般会指定一个绑定键BindingKey),这样RabbitMQ就知道如何正确地将消息路由到队列了,
这里的BindingKey可以理解为匹配RoutingKey的表达式,例如上图的BIndingKey1=*.order,BindingKey2=*.goods,RoutingKey=oms.order,则消息会被发送包Queue1中。
3.1、交换器类型
- fanout
所有送到该换器的息路由所有与该交换器绑定的队列中。
- direct
消息路由到那些BindingKey和RoutingKey完全匹配的队列中。
- topic
direct可以认为是完全匹配,topic是模糊匹配,*表示匹配一个,#表示匹配0个或多个。
- headers
headers类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中headers属性进行匹配。在绑定队列和交换器时制定一组键值对,当发送消息到交换器时,RabbitMQ会获取到该消息的headers进行匹配。headers类型的交换器性能会很差,而且也不实用。
4、RabbitMQ运转流程
RabbitMQ运转流程
- 创建链接
创建和销毁一个TCP链接的开销是高昂的,所以RabbitMQ采用类似NIO的做法,采用TCP链接复用,一个线程一个channel信道,多个channel信道复用一个connnection。
当流量大到某个阈值,需要开辟多个connection,将多个channel均摊到connection中。
- 生产过程
(1)生产者连接到RabbitMQBroker,建立一个连接(Connection),开启一个信道(Channel)。一个connection链接可以开启多个channel。
(2)生产声明一个交换器,并设置相关属性,比如交换机类型、是否持久化等。
(3)生产者声明一个队列井设置相关属性,比如是否排他、是否持久化、是否自动删除等。
(4)生产者通过路由键将交换器和队列绑定起来。
(5)生产者发送消息至RabbitMQBroker,其中包含路由键、交换器等信息。
(6)相应的交换器根据接收到的路由键查找相匹配的队列。
(7)如果找到,则将从生产者发送过来的消息存入相应的队列中。
(8)如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者。
(9)关闭信。
(10)关闭连接。
- 消费过程
(1)消费者连接到RabbitMQBroker,建立一个连接(Connection),开启一个信道(Channel)。一个connection链接可以开启多个channel。
(2)消费者向RabbitMQBroker请求消费相应队列中的消息,可能会设置相应的回调函数,以及做一些准备工作。
(3)等待RabbitMQBroker回应并投递相应队列中的消息,消费者接收消息。
(4)消费者确认(ack)接收到的消息。
(5)RabbitMQ从队列中删除相应己经被确认的消息。
(6)关闭信道。
(7)关闭连接。
参考:
《RabbitMQ实战指南》