约定

下面出现的无特殊说明都是按下面对应关系

Publishers(发布者/生产者)

Consumers(消费者)

Exchanges(交换机)

Broker(中间件)

Queues(队列)

Bingdings(绑定)

AMQP是什么

AMQP是Advanced Message Queuing Protocol的缩写,高级消息队列协议,是一种消息传递协议

中间件和角色

消息中间件从Publishers(发布者/生产者)接收消息,路由到Consumers(消费者)

因为AMQP是网络协议, 发布者,消费者,中间件能够在不同的机器上.

AMQP模型简介

AMQP模型有下面的视角:

  1. 消息被发布到交换机(exchange,通常被比作邮局或邮箱)
  2. 交换机(exchanges)根据绑定(bindings)规则把消息复制到队列(queues)
  3. 中间件(borker)把消息投递到订阅队列或者从队列中拉取的消费者(consumers) view

当一个消息发布时, 生产者可以设置一些消息属性(消息元数据meta data).一些元数据被中间件使用,剩下其他的被不透明发送到中间件给应用程序使用.

网络是不可靠的,应用也有可能处理消息失败,AMQP 0-9-1有一个消息应答(acknowledgements)的概念:当一个消息派发给消费者,消费者会通知中间件,可以自动执行或者开发者选择执行.当使用消息确认时,收到消息的通知就会从队列里删除该消息.

在某些情况,比如一个消息无法被路由,消息将会返回给生产者,丢弃,或者如果中间件实现一个扩展放入死信队列.生产者通过发布消息携带某些参数来处理这些情况.

队列(queue)、交换机(exchanges)和绑定(bingdings)统称为AMQP实体.

AMQP是一个可编程的协议

AMQP是一种可编程协议,AMQP的实体和路由方案主要由应用程序自己定义,而不是由中间件管理员定义.因此,为声明队列和交换机、定义它们之间的绑定、订阅队列等操作做出了规定.

这给应用程序开发者很大的自由,但是这也要求他们意识到潜在的定义冲突,在实践中定义冲突很少,通常是配置错误。

应用定义他们需要的实体,定义必要的路由规则和不在使用时删除实体

交换机和交换机类型

交换机是向其发送消息的AMQP实体,交换机接收消息并将其路由到零个或多个队列中。使用的路由算法取决于交换机类型和绑定,AMQP协议提供四种交换机类型:

交换机类型默认名称
Direct exchange(直接交换机)(Empty string) and amq.direct
Fanout exchange(扇出交换机)amq.fanout
Topic exchange(主题交换机)amq.topic
Headers exchange(头交换机)amq.match (and amq.headers in RabbitMQ)

除了交换机类型之外,交换机还使用许多属性来声明,其中最重要的是:

  1. Name (名称)
  2. Durability (中间件重启后持久化)
  3. Auto-delete (最后一个队列解除绑定自动删除)
  4. Arguments (参数,可选的, 由插件和中间件特定功能使用)

交换机可以是持久的或者是临时的,持久性交换机在中间件重启后仍能存在,而暂时性交换机则不能.并非所有场景和用例都要求交换机持久化.

默认交换机

默认交换机是一个没有名称预定义在broker的直接交换机(direct exchange),它有一个特殊的特性,这使得它对于简单的应用程序非常有用:每个被创建的队列都会用和队列名称相同的路由键(routing key)自动绑定默认交换机.

例如: 当你创建一个名字叫search-indexing-online的队列, AMQP使用search-indexing-online作为路由键(在此上下文中,有时称为绑定密钥)绑定到默认交换机.因此,一个路由键为search-indexing-online的消息发布到默认路由器时将被路由到search-indexing-online队列,默认交换机就好像消息直接投递到队列

直接交换机(direct exchange)

直接交换机根据消息路由键将消息传递到队列。直接交换机是消息单播路由的理想选择(尽管它们也可用于多播路由)下面是它的工作原理:

  1. 一个队列用路由键K绑定到交换机
  2. 当一个路由键为R的消息到达直接交换机,交换机会路由到K=R的队列

直接交换通常用于在多个workers之间分发任务使用循环的方式分发.当要这么做时,需要了解一个重要的事情,在AQMP中消息时在消费者之间负载均衡,而不是在队列间负载均衡. 直接交换可以用图形表示如下: view

扇出交换机(fanout echange)

扇出交换机投递消息会忽略路由键,投递到所有绑定到交换机的队列上.如果N个队列绑定到一个扇出交换机,则当新消息发布到该交换机时,将向所有N个队列传递该消息的副本,扇出交换是消息广播路由的理想选择。

因为扇出交换将消息的副本传递给绑定到它的每个队列,所以它的用例非常相似:

  1. 大型多人在线(MMO)游戏可以将其用于排行榜更新或其他全局活动
  2. 体育新闻网站可以使用扇出交换机将分数更新近乎实时地分发给移动客户端
  3. 分布式系统可以广播各种状态和配置更新
  4. 群聊可以使用扇出交换在参与者之间分发消息(尽管AMQP没有内置的状态概念,因此XMPP可能是更好的选择)

扇出交换机可以用以下图形表示: view

主题交换机(topic exchange)

主题交换机将消息路由到一个或多个队列基于匹配消息的路由键和队列绑定到交换机的模式,主题交换机类型通常用于实现各种发布/订阅模式变体,主题交换机通常用于消息的多播路由。主题交换机有非常广泛的用例集.当一个问题涉及多个消费者/应用程序,这些消费者或应用程序有选择地选择他们想要接收哪种类型的消息时,应该考虑使用主题交换。

头交换机(headers exchange)

标头交换机是为在多个属性上进行路由而设计的,这些消息的头属性比路由键更容易表示.头交换机会忽略路由键,使用头属性路由.如果标头的值等于绑定时指定的值,则认为消息匹配。可以使用多个匹配头将队列绑定到头交换机.开发者需要考虑匹配任意一个还是所有.这就是“x-match”绑定参数的作用。当“x-match”参数设置为“any”时,只匹配到一个头值就够了.或者将“x-match”设置为“all”要求所有值必须匹配。

对于“any”和“all”,以字符串x-开头的头将不用于计算匹配.将“x-match”设置为“any-with-x”或“all-with-x”将使用以字符串x-开头的头来评估匹配。

头交换机可以看成是直接交换机的衍生.因为是基于头的值路由,可以把头当成路由键,可以不是字符串.