1

一、Rabbit路由协议——AMQP协议

AMQP(Advanced Message Queuing Protocol,高级消息队列协议)是一个网络协议。它支持符合要求的客户端应用和消息中间件代理之间进行通信。主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。

简单点说就是在异常通讯中,消息不会立即到达接收方,而是被存放到一个容器中,当满足一定的条件之后,消息会被容器发送给接收方,这个容器就是消息队列(MQ),而完成这个功能需要双方和容器以及其中的各个组件遵循规则,AMQP就是这样一种协议,消息发送和接收的双方都要遵守。

AMQP机制为:消息(message)被发布者(publisher)发送给交换机(exchange),交换机将收到的消息根据路由规则发给绑定的队列(queue)。最后AMQP代理会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取,如图:

image
这是一个简单的“Hello,world”示例,从发布者到生成者消息的大致流向,其中还省略了一些AMQP实际的组件细节。这里主要包括以下一些组件:

Publisher:数据的发送方。
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列,这里的规则后面会有介绍。
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
Consumer:数据的接收方。

总的AMQP的结构图如下所示:
image

发布者(Publisher)

发布者发布消息时可以给消息指定各种消息属性(message meta-data)。有些属性有可能会被消息代理(Brokers)使用,然而其他的属性则是完全不透明的,它们只能被接收消息的应用所使用。

从安全角度考虑,网络是不可靠的,接收消息的应用也有可能在处理消息的时候失败。基于此原因,AMQP模块包含了一个消息确认(message acknowledgements)的概念:当一个消息从队列中投递给消费者后(Consumer),消费者会通知一下消息代理(Broker),这个可以是自动的,也可以由处理消息的应用的开发者执行。当“消息确认”被启用的时候,消息代理不会完全将消息从队列中删除,直到它收到来自消费者的确认回执(acknowledgement)。

在某些情况下,例如当一个消息无法成功路由时,消息或许会返回给发布者并被丢弃。或者,如果消息代理执行了延期操作,消息会被放入一个所谓的死信队列中。此时,消息发布者可以选择某些参数来处理这些特殊情况。

信道(Channel)

信道是多路复用连接中的一条独立的双向数据流通道,为会话提供物理传输介质。Channel是在connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的channel进行通讯,AMQP method包含了channel id帮助客户端和message broker识别channel,所以channel之间是完全隔离的。Channel作为轻量级的Connection极大减少了操作系统建立TCP connection的开销。在客户端的每个连接里,可建立多个Channel,每个Channel代表一个会话任务。

服务端(Broker)

其实Broker就是接收和分发消息的应用,也就是说RabbitMQ Server就是Message Broker。

虚拟主机(Virtual Host)

虚拟主机,一批交换器(Exchange),消息队列(Queue)和相关对象。虚拟主机是共享相同身份认证和加密环境的独立服务器域。同时一个Broker里可以开设多个vhost,用作不同用户的权限分离。

连接(Connection)

连接,一个网络连接,比如TCP/IP套接字连接。Channel是建立在Connection之上的,一个Connection可以建立多个Channel。

消息体(Message)

消息体,是AMQP所操纵的基本单位,它由Producer产生,经过Broker被Consumer所消费。它的基本结构有两部分: Header和Body。Header是由Producer添加上的各种属性的集合,这些属性有控制Message是否可被缓存,接收的Queue是哪个,优先级是多少等。Body是真正需要传送的数据,它是对Broker不可见的二进制数据流,在传输过程中不应该受到影响。

交换机(exchange)

交换机是用来发送消息的AMQP实体。交换机拿到一个消息之后将它路由给一个或零个队列。它使用哪种路由算法是由交换机类型和被称作绑定(bindings)的规则所决定的。

四种交换机:

  • Direct exchange(直连交换机)
  • Fanout exchange(扇型交换机)
  • Topic exchange(主题交换机)
  • Headers exchange(头交换机)

交换机可以有两个状态:持久(durable)、暂存(transient)。持久化的交换机会在消息代理(Broker)重启后依旧存在,而暂存的交换机则不会(它们需要在代理再次上线后重新被声明)。然而并不是所有的应用场景都需要持久化的交换机。

交换机的几个重要属性:

  • Name
  • Durability (消息代理重启后,交换机是否还存在)
  • Auto-delete (当所有与之绑定的消息队列都完成了对此交换机的使用后,删掉它)
  • Arguments(依赖代理本身)

队列

AMQP中的队列(Queue)跟其他消息队列或任务队列中的队列是很相似的:它们存储着即将被应用消费掉的消息。队列跟交换机共享某些属性,但是队列也有一些另外的属性。

  • Name
  • Durable(消息代理重启后,队列依旧存在)
  • Exclusive(只被一个连接(connection)使用,而且当连接关闭后队列即被删除)
  • Auto-delete(当最后一个消费者退订后即被删除)
  • Arguments(一些消息代理用他来完成类似与TTL的某些额外功能)

队列在声明(declare)后才能被使用。如果一个队列尚不存在,声明一个队列会创建它。如果声明的队列已经存在,并且属性完全相同,那么此次声明不会对原有队列产生任何影响。如果声明中的属性与已存在队列的属性有差异,那么一个错误代码为406的通道级异常就会被抛出。

绑定(Binding)

绑定是交换机将消息路由给队列所需遵循的规则。如果要指示交换机“E”将消息路由给队列“Q”,那么“Q”就需要与“E”进行绑定。绑定操作需要定义一个可选的路由键(Routing Key)属性给某些类型的交换机。路由键的意义在于从发送给交换机的众多消息中选择出某些消息,将其路由给绑定的队列。

打个比方:

队列(Queue)是我们想要去的目的地
交换机(Exchange)是一个转换站,比如车站
绑定(Binding)就是车站到目的地的路线。能够到达目的地的路线可以是一条或者多条
拥有了交换机这个中间层,很多由发布者直接到队列难以实现的路由方案能够得以实现,并且避免了应用开发者的许多重复劳动。

二、RabbitMQ的工作流程介绍

  1. 建立信息。Publisher定义需要发送消息的结构和内容。
  2. 建立Conection和Channel。由Publisher和Consumer创建连接,连接到Broker的物理节点上,同时建立Channel。Channel是建立在Connection之上的,一个Connection可以建立多个Channel。Publisher连接Virtual Host 建立Channel,Consumer连接到相应的Queue上建立Channel。
  3. 声明交换机和队列。声明一个消息交换机(Exchange)和队列(Queue),并设置相关属性。
  4. 发送消息。由Publisher发送消息到Broker中的Exchange中
  5. 路由转发。RabbitMQ收到消息后,根据​​消息指定的Exchange(交换机) 来查找Binding(绑定) 然后根据规则(Routing Key)分发到不同的Queue。这里就是说使用Routing Key在消息交换机(Exchange)和消息队列(Queue)中建立好绑定关系,然后将消息发送到绑定的队列中去。
  6. 消息接收。Consumer监听相应的Queue,一旦Queue中有可以消费的消息,Queue就将消息发送给Consumer端。
  7. 消息确认。当Consumer完成某一条消息的处理之后,需要发送一条ACK消息给对应的Queue。

    • Consumer收到消息时需要显式的向RabbitMQ Broker发送basic.ack消息或者 Consumer订阅消息时设置auto_ack参数为true。
    • 在通信过程中,队列对ACK的处理有以下几种情况:
    • 如果Consumer接收了消息,发送ack,RabbitMQ会删除队列中这个消息,发送另一条消息给Consumer。
    • 如果Consumer接收了消息, 但在发送ack之前断开Channel,RabbitMQ会认为这条消息没有被deliver(递送),如果有其他的Channel,会该消息将被发送给另外的Channel。如果没有,当在Consumer再次连接的时候,这条消息会被redeliver(重新递送)。
    • 如果consumer接收了消息,但是忘记了ack,RabbitMQ不会重复发送消息。
    • 新版RabbitMQ还支持Consumer reject某条(类)消息,可以通过设置requeue参数中的reject为true达到目地,那么Consumer将会把消息发送给下一个注册的Consumer。
  8. 关闭消息通道(channel)以及和服务器的连接。

柠檬时间
63 声望5 粉丝

遵循内心


引用和评论

0 条评论