AMQP 0-9-1模型

Overview

01 什么是AMQP 0-9-1模型
AMQP 0-9-1(Advanced Message Queuing Protocal)是确保客户端与消息代理软件通信的协议。

02 代理(Brokers)
消息代理接收发布者(Publisher)发布的消息,并把这些消息转发给消费者(Consumer)。该协议是一个网络协议,所以发布者,消费者和代理可以工作在不同的机器上。

03 AMQP 0-9-1模型
AMQP 0-9-1模型的工作过程为:
1.Publisher将message发布到exchange(exchange可以看作是一个邮局或者邮件系统,也就是Broker)
2.然后exchange将message发送到queue(队列),这个过程称之为bindings(绑定)。
3.AMQP Broker或者将message发送给订阅(subscribed)queue的consumer,或者consumer按需将message从queue中取出来。
这里写图片描述

发布messages时,publisher可以使用各种消息属性(message-meta-data),meta-data中的一部分可以被Broker使用,但是剩下的那部分对Broker不是透明的,只能被接收message的应用程序所使用。

Networks是不可靠的,应用可能处理消息失败,所以AMQP模型有消息确认机制(message acknowledgements)。当消息分发给consumer后,consumer或者自动或者按开发者所选择的那样尽快向broker发送确认消息。当消息确认开启时,broker只有在consumer发送接收消息的确认信息后才会将message从queue中移除。

当message不能被路由到consumer时,该message或者返回给publisher,或者丢弃或者移到”dead letter queue”(broker 的扩展部件)。publisher可以通过特定的参数处理这种情况。

04 AMQP是可编程的协议
AMQP 0-9-1 是一个可编程的协议,这意味着AMQP 0-9-1的实体(entities)和路由主体(routing schemes)是由应用程序控制的,而不是broker。AMQP包括声明(declare) queue和exchanges,两者之间的binding,订阅queue等等。

这给予开发者很大的自由但是也要意识到其中潜在的定义冲突。实际中,定义冲突是不常见的而且往往是由于错误的配置引起的。

应用按需创建AMQP entitles,定义必要 的routing schemes,当entities不再需要时也可以将至删除。

Exchanges和Exchange Types

publisher将message发送给Exchanges,然后Exchanges将此消息转发给queue(可以是多个,也可以是0个)。routing算法取决于exchange type,成为binding。AMQP提供四种exchange types:

  • Direct exchange:默认的声明名字为空或者amq.direct
  • Fanout exchange:默认声明的名字为amq.fanout
  • Topic exchange:默认声明的名字为amq.topic
  • Headers exchange:默认声明的名字为amq.match(在rabbitmq中是amq.header)

除了这几种exchange type外,exchange还具有一些属性,其中最重要的是:
- Name
- Durability(broker重启时生效)
- Auto-delete(当最后一个queue解绑时将自动删除)
- Arguments(可选的,由插件和代理的特定功能使用)

exchange可以是durable(持久)或transient(短暂)。Durable exchange在broker重启时生效。而transient则不是,当broker上线时则必须重新创建。并不是所有的场景都必须要求exchange是durable。

01 Default Exchange
默认的exchange是direct exchange,声明时的名字为空。这种方式的特征为:当queue名称与routing key相同时将自动使queue与之绑定 。

举例来说,当你声明一个名字为”search-indexing-online”的queue时,broker会将queue绑定到routing key为”search-indexing-online”的default exchange。所以,publish到routing key为”search-indexing-online”的default exchange的message会被routed到名字为”search-indexing-online”的queue。也就是说,default exchange会将message直接分发给queues。

02 Direct Exchange
Direct Exchange依据routing key分发message,direct exchange是单播的理想选择(也可以用于多播),下面是该模式的工作原理:
queue(名字为K)与exchange绑定,当新的message(routing key =R)到达direct exchange时,exchange将message转发给k=R的queue。

Direct exchanges也可以在多个works之间发布任务(以循环的方式)。这种方式时必须理解message在consumer之间是负载均衡的而不是在queue之间。
Direct exchange routing可以用下图来表示:
这里写图片描述

03 Fanout Exchange
fanout exchange将message route到所有与之绑定的queue(忽略routing key),如果n个queue与fanout exchange绑定,那么当message到达exchange时,exchange会将message分发给这n个queue。fanout exchange是广播的理想选择。

fanout exchange将message分发给所有与之绑定的queue,它所应用的场景是非常类似的:

  • 大型多人在线(Massively Multi-player Online,MMO)游戏可以将其用于排行榜更新或其他全局性的事件;
  • 体育新闻网站可以使用fanout exchange近乎实时地向移动客户端分发分数更新;
  • 分布式系统可以广播多种状态和配置更新;
  • 群聊可以使用fanout Exchang在参与者之间发布messages(AMQP没有这种内置的场景,XMPP是更好的选择)。

    fanout exchange可以用下图来表示:
    这里写图片描述

04 Topic Exchange
Topic Exchange依据匹配规则(与routing key和用于将queue绑定到exchange的模式有关)将message分发给一个或者多个queue。Topic Exchange常用于实现各种pub-sub模式的变体。Topic Exchange 通常用于message的组播路由。

Topic Exchange有非常多的应用场景,当一个问题涉及多个consumer/application按需接收messages时就要使用Topic Exchange。

使用的例子:

  • 分配与特定地理位置相关的数据时,如销售点;
  • 多个workers处理后台任务,每个能够处理特定的一组任务;
  • 股票价格更新(其他的经济数据更新同样适用);
  • 涉及分类或者标记的新闻更新(如仅仅适用于特定的运动或者团队);
  • 在云中调配不同种类的服务;
  • 分布式架构/特定操作系统的软件构建或打包,这里每个处理器只能处理一个架构或操作系统

05 Headers Exchange

Headers Exchange是在多个属性上进行routing,这些属性相比于routing key更容易被表示成message header。headers exchange忽略routing key。如果message的header的值等于绑定时的值,则认为匹配成功。

使用多个header用于匹配也是可以的。这种情况下必须考虑:是任意的header匹配就认为匹配成功还是所有的headers必须都匹配才认为匹配成功,这可以使用x-match的参数进行配置,x-match参数:

  • 当x-match绑定参数设置为”any“时,只有一个匹配的header就认为匹配;
  • 当x-match绑定参数设置为”all“时则要求所有的值都必须匹配才认为匹配成功。

Headers Exchange可以看作是routing key不必是String(可以是整数或者散列/字典)的Direct Exchange。

Queues

在AMQP模型中,queues与其他message-和task- queueing系统相似:存储consumer需要的message。Queues相比exchange有以下附加特性:

  • Name;
  • Durable(broker重启时queue生效);
  • Exclusive(仅可被一个connection使用并且当连接关闭时会删除queue);
  • Auto-delete(当没有consumer订阅该queue时会自动删除);
  • Arguments(可选的,被插件或者特定的broker特性所使用,如message的TTL,queue长度限制等等);

在使用queue之前必须声明它,当queue不存在时声明该queue会自动创建queue。声明一个已经存在的queue将没有任何影响,声明的属性必须要与queue的属性相同。当声明的queue的属性与queue的属性不同时将会出现channel-level的异常(代码是406 PRECONDITION_DAILED)。

01 Queue Name
应用可以自己选择queue name也可以让broker为它生成一个name,。queue name最长可以是266字节的utf-8字符。broker可以生成独一无二的queue name。

以”amq.“开头的queue名称时留给broker内部使用的,声明违反命名规则的queue将导致channel-level的异常(code 403,ACCESS_REFUSED)。

02 Queue Durability
Durable queue存储到磁盘,所以会在代理重启后继续运行。与之对应的queue称之为transient queue。并不是所有的场景都要求queue是Durable。

Durability queue不会使routed到这个queue的message持久,如果broker被取消,然后被备份,Durable queue将在代理启动期间被重新声明,只有持久的message会被恢复。

Bindings

Binding是使exchanges将message路由到queue的规则。如exchange E要将message路由到queue Q,那么Q则必须要绑定到E。Bindings在一些exchange type中可以不需要routing key属性,routing key的作用就是选择那些与exchange绑定的queue,换句话说,routing key就像一个滤波器。

举例来说:queue就像您的目的地纽约,Exchanges像JFK机场,Bindings就是JFK机场到纽约的路由,可以有0或者多个路由。

这种间接层可以使使用直接发布到队列的方式实现不可能或很难实现的路由场景,而且还消除了开发人员必须做的一些的重复工作。

如果AMQP message不能被路由到任何一个queue(如没有任何queue与exchange绑定的情景),那么该message或者被丢弃或者返回给publisher,这取决于publisher设置的消息属性。

Consumer

在queue中存储message是无用的,除非有Application可以使用它,在AMQP中,Application使用message的方式有两种:

  • 分发message给Application(“push API”);
  • Application按需从queue中取消息(“pull API”)。

在push API 中,application必须表明它对于特定queue中message的”兴趣”,这种行为称之为”register consumer”或”put subscribe to a queue”。一个queue可以有多个consumer或者特定的consumer。

每一个consumer都有一个consumer tag(身份标识),这可用于取消订阅message。consumer tag仅仅是Strings。
01 Message Acknowledgements
application(用于接收和处理message)可能会发生处理失败的情况(不合法的message,网络原因等)。这就出现一个问题:AMQP broker什么时候将message从queue中移除?AMQP给出了两种选择:

  • 在broker将message发送给application后(使用basic.deliver或者basic.get-ok);
  • 在application发送acknowledgement(使用basic.ack)。

第一种选择称之为自动确认模型,第二种选择称之为显式确认模型。在显示确认模型种,确认消息可以在接收message后或处理message之前或在完全处理消息之后(例如:成功的住区网页,处理和将至存储到磁盘中)。

如果一个consumer在未发送确认之前就died,那么broker会将message重新分发给另外一个consumer,如果没有其他可用的consumer,broker等待直到注册新的consumer。

02 Rejecting Messages
consumer应用接收到message,但是可能会处理失败。application则要向broker表明处理失败(或者不能按时完成)来拒绝message。当拒绝message时,application可以要求broker丢弃这个message或者重新分发(给其他consumer),当只有一个consumer application时,一定要确保该message不会再分发给自身,这样就会进入一个死循环。

03 Negative Acknowledgement

basic.reject方法用于拒绝message,但是有一个限制:没有办法拒绝多个message。有一个解决方法:Rabbitmq提供了一个AMQP 0-9-1扩展成为Negative Acknowledgement或nacks,详见http://www.rabbitmq.com/nack.html.

04 Prefetching Messages

一个queue有多个consumers时,在发送下一个确认之前确认每个consumer可以分发多少message时非常有用的。这可以用作简单的负载均衡技术或者如果message要批量发布时,则可以提高吞吐量(例如,如果producer应用由于正在进行的工作性质而每分钟发送message时)。

Message Attributes and Payload

AMQP中的message都有属性。一些属性是非常常见的,应用开发者见到就能知道这些属性所代表的意思。如:

  • Content type;
  • Content encoding;
  • Routing key;
  • Delivery mode(是否持久);
  • Message priority;
  • Message publishing timetamp;
  • Expiration period(到期期限);
  • Publisher application id;

一些属性供broker所使用,但是大部分的属性是对消息的解释说明。一些属性是可选的(headers),这与HTTP中header是非常相似的。message的属性是在message发布的时候设置。

Message同样有负载(所携带的数据),broker将负载看作不透明的数据流,不会检查或者更改负载。Message只包含属性不包含负载也是可以的。负载通常使用的序列化格式有:JSON,Thirft,Protocol Buffers和MessagePack。AMQP对等方通常使用“content-type”和“content-encoding”来传递message,但这仅仅是惯例。

Message Acknowledgements

因为网络的不可靠性和应用程序可能处理message失败,所以确认机制是必不可少的。有时,只需确认接收方已经成功接收了message即可,有时则必须确认message已经验证通过或者处理完成了。

这种情形是非常常见的,所以AMQP引入了Message Acknowledgements(Acks),用于确认Consumer已经接收message或者处理message。如果一个application宕机了(与broker断开连接了)或者确认消息没有到达broker,那么message会被重新下发(如果存在其他的consumer,则立即下发)。

该机制可以使开发人员开发更为强大的软件。

AMQP的方法

AMQP有很多结构化的方法,方法就是操作(如HTTP方法),这与面向对象编程的语言的方法并没有共同之处。详见AMQP Reference.

在exchange类中的方法有:

  • exchange.declare
  • exchange.declare-ok
  • exchange.delete
  • exchange.delete-ok
    前两个和后两个逻辑上是一对操作,一个是请求,一个是响应。

client使broker声明一个新的exchange使用exchange.declare
这里写图片描述

如果操作成功,那么broker会响应,使用exchange.declare-ok,该方法除了channel号不携带任何的参数。
这里写图片描述

exchange.deleteexchange.delete-ok如下图所示:
这里写图片描述

并非所有的操作都有都有相对应的操作,如basic.publish;也并非所有的操作都只有一个相对应的操作,如basic.get

Connetcion

AMQP 的connection通常是长期存在的。AMQP是应用层协议,通常使用TCP连接进行可靠的分发,AMQP连接使用身份验证机制,可以使用TLS(SSL)进行保护。当应用程序不再需要连接到AMQP代理程序时,应当在上层关闭TCP连接,而不是突然断开底层的连接。

Channels

一些应用需要多个与broker的Connection,但是在同一时间保持多个TCP连接会消耗大量的系统资源并且不利于防火墙的配置。AMQP的连接是通过channel进行复用的,多个channel共用一个connection,可认为是一个轻量级的TCP connection。

对于一个多线程的应用来说,每一个线程都声明一个channel是非常常见的,线程之间并不共享Channel。

在特定channel上的通信是与另一个channel上的通信完全分离的,所以AMQP方法携带channel号以区分channel。

Virtual Hosts

为了使单个broker可以有多个独立的“环境”(用户组,exchange,queue等等),AMQP引入Virtual Hosts机制。它们与许多主流的Web Server相似并且提供完全隔离的AMQP实体环境。AMQP客户端在连接协商期间指定他们想要连接的Vhost。

AMQP是扩展的

AMQP有许多可扩展的点:

  • Customer exchange type:使开发者可以开发路由主题(exchange type);
  • 在声明exchange和queue时可以包附件的属性以供broker使用;
  • 新的AMQP方法;
  • broker也可扩展新的组件(Rabbit management frontend和HTTP API)。

AMQP 0-9-1客户端生态系统

AMQP客户端支持多种主流的编程语言和平台。详见http://www.rabbitmq.com/devtools.html

本篇文章是在官方文档的基础上翻译的,有些翻译的不是很好,附上原文地址以供参考!原文地址

猜你喜欢

转载自blog.csdn.net/gaoyang8320/article/details/78312587
今日推荐