RabbitMQ (AMQP 0-9-1模型解释) 译

下面是根据官网文档做的一个笔记,大部分来自于翻译,加了点个人理解,错误之处及时纠正前来打脸

概要

AMQP 0-9-1 协议

AMQP 0-9-1模型(Advanced Message Queuing Protocol 高级消息队列协议),使得遵循协议的客户端应用程序可以与相应的消息中间件进行通信,该协议 是RabbitMQ支持的消息协议之一。

broker角色

消息代理(broker)从生产者/发布者接收消息,并路由给消费者。生产者/消费者/broker可以分布在不同的机器上。 对于RabbitMQ, RabbitMQ就相当于broker的角色. rabbit

AMQP 0-9-1 模型概要

对于AMQP 0-9-1模型,消息发布到exchange, exchange常比作邮局,exchange负责将消息的副本根据路由规则发送到匹配的queue,
此处的路由规则被称为bindings,随后broker将消息投递给订阅某些queue的消费者,或者消费者主动拉取所需要的消息。

当发布消息时,消息会带有各种属性(消息元数据),部分元数据属性会被broker使用,剩下部分的则对broker来说是不可见的,
该部分只会被接收该消息的应用所使用

由于存在网络的不可靠或者应用本身消息处理失败的情况,AMQP 0-9-1模型有一个消息确认的概念。当消息发送给消费者,
消费者需要通知broker消息已处理,该动作可以是自动的也可以是开发者负责何时响应确认消息。
如果消息确认机制启用,则broker只有收到消息确认后才会从队列中完全移除消息。

某些情况下,当消息无法被路由到某个queue时,消息会被返回给生产者或者忽略掉。
如果broker实现了扩展功能,可以将这类消息放入死信队列(dead letter queue). 生产者可以通过消息参数设置来选择该种情况如何处理。

Queues、exchanges、bindings都是AMQP的实体。

AMQP 0-9-1是一个可编程协议,AMQP的实体和路由方案都有应用程序本身定义,不是由broker定义。协议规则只是制定了在queues、exchange以及 他们之间如何bindings,以及如何订阅queue等规则。因此应用开发者可以更灵活的使用,可以在需要的时候定义AMQP0-9-1的实体,不需要时候删除即可。

组成&概念

exchange 交换机

消息发送到exchange,exchange会将消息路由到0或多个queue中,路由规则依赖于exchange的类型和路由规则binding. exchange有几个比较重要的属性:

  • name,exchange的名称
  • Durability, 持久性,是否broker重启时可恢复。并非所有的场景都需要持久化消息
  • Auto-Delete, 自动删除,是否绑定在exchange上的最后一个queue解绑后自动删除
  • Arguments, 参数,可选,用于插件和特定broker的特性

exchange目前由4种类型:

  • Direct 名称为空或者amq.direct,单播消息,默认就是direct类型的exchange。

        在声明exchange时不指定名称或者指定amq.direct类型时,就是direct类型exchange, 该类型exchange会在每个queue自动创建时绑定routing key
     ,routing key此时就是每个queue的名称。当声明一个queue时,将自动绑定默认exchange,并使用queue的名称作为routing key路由消息,当收到消息带有
     该routing key时,exchange将其投递到对应名称的queue中。
        direct exchange常用于任务轮询的分发给多个consumer(处理相同业务逻辑的一个应用的多个实例),注意,负载均衡实在consumer处实现的
    而不是在queue处。
  • Fanout amq.fanout,广播消息,会将收到的消息复制发送给绑定该exchange的所有queue,routing key将会被忽略

        此类广播消息通常的应用场景有下面几个:
        - 多人在线游戏, 广播实时排行等全局消息
        - 体育比赛新闻,实时广播比分
        - 分布式系统中,广播状态变化和配置更新
        - 群聊,广播消息给群内所有成员(即时消息不是amqp的内置概念,即时消息XMPP实现会是更好的选择)
  • Topic 主题类型,amq.topic, 主题类型消息路由,可以将消息路由到一个或多个queue, 该exchange可以绑定routing key或者模式表达式对应的一个或多个queue。

        topic exchange 使用范围很广,当需要在多个消费者或者应用间有选择性的消费处理消息时,考虑使用该exchange类型
        部分应用场景:
        - 分发地理位置相关的数据,例如,销售网点
        - 后台任务,多个worker处理不同类型的任务集合
        - 股票价格更新(多种类型的财务数据)
        - 特定标签和分类的新闻更新
        - 不同类型的云服务编排
        - 分布式系统或者特定操作系统构建或打包,每个builder处理器可以处理不同类型的操作
  • Headers 头类型,amq.match/amq.headers,设计用于消息头的形式路由多个属性而不是通过routing key实现,此时routing key将被忽略, 路由规则此时使用header中的属性,当header中属性与binding的值相同时,认为消息匹配。

        headers exchange支持通过一个或者多个头匹配路由规则,此匹配模式,有一个x-match绑定参数,当x-match值为any时,headers中有一个
    匹配的即可;当x-match值为all时,必须所有header都匹配。
        headers exchange可以看作是一个特殊的direct exchange,不过与direct不同的是,headers exchange基于header头路由匹配规则,
    它的routing key不必是string字符串,可以是int、字典等类型
        注:当header中的key以 x- 开头时将不会用于评估匹配的计算。

queue 队列

queue和其他消息系统类型,用于存储被消费者消费的消息,queue和exchange共享一些属性,但是也有其他的属性:

  • name 队列名称

    应用可以传递一个queue名称或者通过broker生成一个队列名称,队列名称长度限制为255个字节utf-8编码字符,broker可以为一个应用 生成为一个队列名称,如果需要使用broker生成队列名称,传递空字符串即可,生成的名称将会在响应体中。

    注意:队列名称不能以amp.开头,该关键字为broker内部保留使用,如果使用将会抛出403 ACCESS_REFUSED异常

  • Durable 持久性,broker重启是否数据可恢复

    队列持久化是将队列持久化到磁盘,非持久化的队列为瞬态队列,并非所有场景都需要持久化数据.

    持久化队列不会让已路由到该队列的消息持久化,如果broker down然后恢复,在broker启动期间持久化队列会重新声明,但是只会恢复持久化的消息。

  • Exclusive 独占,只能有一个连接使用该队列,当连接关闭时,队列自动删除

  • Auto-delete 自动删除,是否最后一个消费者不再订阅时自动删除

  • Argument 参数, 可选,用于插件和特定的broker,例如配置消息的ttl、队列的ttl、队列长度限制、队列的死信处理(exchange&routing key)等

    队列使用前必须先声明,如果队列不存在,声明队列将会自动创建。当队列已存在并且声明属性与已存在队列相同则无影响,
  当声明属性与已存在的队列属性不同,将会抛出PRECONDITION_FAILED异常

bindings 路由绑定规则

是一组规则决定exchange将消息路由到哪些queue,queue绑定到exchange,bindings需要一个可选的routing key作为路由规则,然后根据routing key 将消息路由到绑定的队列上。

    可以对exchange、queue、bindings做一个类比:
    queue: 某处大保健按摩院
    exchange:公交车换乘站
    bindings: 就是从公交车换乘站到你要去的大保健按摩院的路线,可以有0个或者多个路线方案(routing key)
    直接发布消息到队列是很难实现的,有bindings这个间接路由层,消除了开发者很多重复性开发工作。当消息不能路由任何队列时,消息会被丢弃或者
  返回给生产者,取决于生产者对消息属性的设置。

consumer 消费者/订阅者

AMQP 0-9-1模型中,消费者应用可以有两种方式获取消息:

  • 推模式Push, broker将消息推给消费者 该模式就相当于消费者对某些队列消息感兴趣,可以说注册了一个订阅者,订阅某些队列的消息。每个队列可以同时有多个消费者或者独占消费者(当 独占消费者消费时,其他消费者不能消费)。每个消费者有一个标识标签tag,可用于取消订阅某些消息,tag为String类型。
  • 拉模式Pull, 消费者根据需要主动拉取消息

消息确认机制,由于网络或者消费者种种原因导致消息处理失败时,提供消息确认机制增加系统健壮性,AMQP0-9-1协议规定了消费者两种控制方式

  • 当broker发送一个消息给应用后, broker使用basic.deliver或者basic.get-ok方法自动确认
  • 当应用发给broker一个确认消息后, broker使用basic.ack方法确认消息
当明确指定由应用程序发送确认消息后,应用程序可以在消息收到或者完全处理完毕后发送确认消息,如果消费者还没来得及发送确认就死掉了,
broker会尝试重新投递消息给其他消费者,如果没有可用的,则broker会等待直到当前queue有可用消费者为止。

消息拒绝机制

  当应用处理消息失败,或者当前时间无法继续处理消息时,可以主动拒绝消息,告诉broker消息丢弃还是重新放入队列。
  注意:如果当前队列仅有一个消费者,要避免死循环的拒绝-入队列操作。

消息预读

  当多个消费者消费同一个队列时,告知每个消费者发送下一个确认消息之后,可以再消费多少消息(防止消费不均衡,偏压),该功能可以用于简单的负载均衡来提高吞吐量,
  如果消息是批量生产的话,例如,生产者每分钟发送一次消息。
  当前RabbitMQ只支持通道级别的预读,不支持连接或者字节数预读。

producer 生产者

生产消息客户端,将消息发送给exchange绑定的queue。

Message 消息体

  • 消息组成
            消息体包含消息属性和payload消息内容,消息属性通常包含:content-type、content-encoding、routing key、delivery mode、message priority、
      publishing timestamp、expiration period、publisher application id等。<br>
            broker会使用部分消息属性,其他属性和payload对broker来说不可见也不关心,payload是byte数组,开发者可以使用json、thrift、protocol buffer、
      messagePack等工具序列化数据放入payload,接收端通过content-type和content-encoding来解析获取数据。
  • 消息持久化
      消息发送时,可以指定持久化属性,broker会将需要持久化的消息持久化到磁盘,如果server重启,不会导致消息丢失。
      注意!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      消息持久化与队列持久化是两码事,消息持久化完全由publisher指定消息是否需要持久化,和队列持久化无关,消息发送到持久化队列,但是消息如果
    不是持久化消息也不会持久化到磁盘,持久化队列仅仅是队列持久化,重启时队列重新声明,保证队列一直存在和消息无关。
      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      注:消息持久化会损失一些性能。

Connections 连接

AMQP 0-9-1 连接协议是长连接应用层协议,底层使用tcp可靠传输。支持使用TLS权限验证。当应用程序不再需要连接到服务器时,应该主动关闭, 而不是暴力关闭。

Channels 通道

依托于connection连接的通道,不单独存在,多个channel会建立在一个connection上,达到tcp连接复用的效果。每个channel拥有一个channelId用于区分, 不同的channel相互隔离。

  一些应用需要多个连接,连接到broker,但是同一时间保持许多tcp连接是不被推荐的,即浪费系统资源也会使得防火墙比较难以配置,AMQP 0-9-1连接
采用多路复用channels,可以认为是轻量级connections共用一个tcp连接。
  客户端的每个连接操作都发生在一个channel上,客户端与多个channel间的通讯是隔离的,因此每个操作方法带有一个channel id,数值类型,broker和
client使用该id判断方法执行在哪个channel上。
  channel不会单独存在,存在于connection中,connection相当于channel的环境上下文,如果connection关闭,则channel就不存在了。
  对于多应用或者多线程间,可能同时打开多个channel,他们之间channel不共享。  

Virtual Host 虚拟主机

为了使broker可以托管多个隔离的环境实体(clients、exchanges、queues等),AMQP 0-9-1引入了Virtual Host概念,和通常意义上的虚拟主机类似,提供完全隔离的运行环境。 客户端在建立连接时指定需要使用的vhosts即可。

目录

概要

AMQP 0-9-1 协议

broker角色

AMQP 0-9-1 模型概要

组成&概念

exchange 交换机

queue 队列

bindings 路由绑定规则

consumer 消费者/订阅者

producer 生产者

Connections 连接

Channels 通道

Virtual Host 虚拟主机

AMQP 扩展性


AMQP支持下面几个扩展点,可供开发者扩展:

  • 自定义exchange类型,让开发者可以实现路由方案,exchange type提供了4中开箱即用的类型,但是没有全部覆盖,如果需要可以自行实现,如根据地理位置的exchange
  • 声明exchange和queue时指定额外属性,broker可以使用这些属性,例如queue ttl属性,RabbitMQ已经实现
  • 特定broker的协议扩展,extension that rabbitmq implments
  • 可以引入新的AMQP 0-9-1方法类,amqp-method
  • brokers的扩展插件,如rabbitMQ management提供前端界面和api接口的插件

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值