RabbitMQ

消息中间

消息中间件是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统.
消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。
优点:解耦、异步、削峰。

Broker:标识消息队列服务器实体.
Virtual Host:虚拟主机。标识一批交换机、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限机制。vhost是AMQP概念的基础,必须在链接时指定,RabbitMQ默认的vhost是 /。
Exchange:交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
Queue:消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
Banding:绑定,用于消息队列和交换机之间的关联。一个绑定就是基于路由键将交换机和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
Channel:信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟链接,AMQP命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说,建立和销毁TCP都是非常昂贵的开销,所以引入了信道的概念,以复用一条TCP连接。
Connection:网络连接,比如一个TCP连接。
Publisher:消息的生产者,也是一个向交换器发布消息的客户端应用程序。
Consumer:消息的消费者,表示一个从一个消息队列中取得消息的客户端应用程序。
Message:消息,消息是不具名的,它是由消息头和消息体组成。消息体是不透明的,而消息头则是由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(优先级)、delivery-mode(消息可能需要持久性存储[消息的路由模式])等。

消息属性

发布的消息包含三个帧: Basic.Publish方法帧、消息头帧和消息体帧

消息头帧:
RabbitMQ

■使用content-type属性让消费者知道如何解释消息体。
■使用content-encoding属性来指示消息体使用某种特殊的方式进行压缩或编码。
■填充message-id和correlation-id来唯-标识消息和消息响应,用于在工作
流程中实现消息跟踪。
利用timestamp属性减少消息大小,并创建一一个 规范定义来描述消息创建时间。
■使用expiration属性表明消息过期。
■告诉RabitMQ使用delivery-mode将消息写入磁盘或内存队列。
■使用app-id和user-id来帮助追踪出现问题的消息发布者应用程序。
■使用type属性来定义发布者和消费者之间的契约。
■使用reply-to属性实现响应消息的路由。
■使用headers映射表定义*格式的属性和实现RabbitMQ路由。

消息发布

使用消息发布者确认机制保证消息的发送可靠.
当发布者发布给所有队列的已路由消息被消费者应用程序直接消费时,或者消息被放入队列并根据需要进行持久化时,一个Basic. Ack请求会被发送到发布者。如果消息无法路由,代理服务器将发送一个Basic.Nack RPC请求用于表示失败。然后由发布者决定该如何处理该信息。

可以使用备用exchanger来处理无法路由的消息

消息持久化:通过设置delivery-mode为2将消息持久化到磁盘.

在IO密集型服务器中,通过操作系统在存储设备之间传输数据时,操作系统将阻塞I/0操作的进程。当RabbitMQ服务器正在尝试执行I/O操作(例如将信息保存到磁盘),并且在等待存储设备响应时操作系统内核发生阻塞,那么RabbitMQ能做的就只有等待。如果RabbitMQ代理服务器经常等待操作系统响应读写请求,消息吞吐量将大大降低。

尽管消息持久化是保障你的消息最终被投递的最重要方式之一,但实现它的代价也是最大的。磁盘性能不佳可能会大大降低RabbitMQ的消息发布速度。在极端情况下,硬件配置不当造成的I/O延迟可能导致消息丢失。简而言之,如果RabbitMQ由于操作系统发生I/0阻塞而无法响应发布者或消费者时,那么消息就不能被发布或投递。

消息消费

RabbitMQ实现了两个不同的AMQP RPC命令来获取队列中的消息: Basic.Get和
Basic. Consume。Basic. Consume。Basic. Get不是从服务器获取消息的理想方法。使用最简单的说法,Basic.Get 是一个轮询模型,而Basic.Consume是一一个推送模型。

Get:当你的应用程序使用Basic. Get请求来获取消息时,每次它想要接收消息就必须发送一个新的请求,即使队列中存在多个消息。当发出一个Basic . Get,如果你想要获取消息的队列中有- -条消息正处于等待处理状态,RabitMQ就会回应-一个 Basic. GetOk RPC响应。如果队列中没有待处理的消息,它将回复Basic.GetEmpty, 表示队列中没有消息

在简单的消息速度测试中,使用Basic.Consume至少是使用Basic.Get的两倍。速度不同的最明显原因是使用Basic.Get会导致每条消息都会产生与RabbitMQ同步通信的开销,这一过程由发送请求帧的客户端应用程序和发送应答的RabbitMQ组成。

Consum:相比之下,通过使用Basic.ConsumeRPC命令来消费消息,你可以使用RabbitMQ注册你的应用程序,并告诉它在消费者可用时以异步方式向消费者发送消息。这通常被称为发布–订阅模式(publish-subscribe pattern,或pub-sub)。 与使用Basic.Get时与RabbitMQ创建的同步会话不同,使用Basic . Consume消费消息意味着你的应用程序会在消息可用时自动从RabbitMQ接收消息,直到客户端发出Basic.Cancel为止。

使用no-ack模式实现更快的吞吐量,不进行确认,代价就是降低可靠性.

一次确认多个消息
使用QoS设置的好处之一就是不需 要用Basic .Ack RPC响应来确认收到的每条消息。相反,Basic.Ack RPC响应具有一个名为multiple的属性,当把它设置为True时就能让RabbitMQ知道你的应用程序想要确认所有以前未确认的消息。

死信交换机:用作保存被拒绝的消息

自动删除队列:drop)一样,自动删除的队列可以被创建并且用来处理消息。一旦消 费者完成连接和检索消息,在断开连接时队列将被删除。
创建自动删除队列非常简单,只需要在Queue . Declare RPC请求中将auto_ delete
标志设置为True即可。

单个消费者的队列:设置为exclusive.

自动过期队列:创建一个自动过期的队列非常简单,要做的事情就是使用x-expires参数声明一个队列,该参数以毫秒为单位设置队列的生存时间(Time To Live,TTL)

延时队列:延时队列就是用来存放需要在指定时间被处理的元素的队列。

队列持久化:将队列的durable设置为true.

消息路由模式

direct:当需要投递的消息有一个确定的目标(或者多个目标)时,direct 交换器就能派上用场。任何绑定在交换器上的队列,只要它的路由键和发布消息时的一致,它就能收到消息。对于direct交换器来说,RabbitMQ在检查绑定时会比较字符串是否相等。此时不允许使用任意类型的模式匹配。

fanout:不同于此,fanout交换器并不作区分。所有发往fanout交换器的消息会被投递到所有绑定到该交换器上的队列中。

topic:类似于direct交换器,topic交换器会将消息路由至匹配路由键的任一队列中。
队列可以通过使用基于通配符的模式匹配的方式来绑定到路由键上。通过使用星号(*) 和井号(#) 字符,你可以在同一时刻匹配路由键的特定部分,甚至是多个部分。星号将会匹配路由键中下一个句点前的所有字符,而井号键将会匹配接下来所有的字符,包括句点。

headers:第四种內建交换器类型是headers交换器。它通过采用消息属性中的headers表支持任意的路由策略。绑定至headers交换器的队列会向Queue.Bind参数中传入键值对数组以及x-match参数。x-match参数是字符串类型,可以设置为any或者all。如果将其设置为any,同时headers表中的值匹配了任何一个绑定值的话,消息就会被路由过去。如果将x-match设置为all的话,那么所有传入Queue.Bind中的参数值必须全部匹配才行。这并不排除消息在headers表中拥有额外的键值对。