RabbitMQ简介上

AMQP(Advanced Message Queuing Protocol)公开标准

解决什么问题

  1. 信息的发送者和接收者如何维持这个连接,如果一方的连接中断,这期间的数据如何方式丢失?
  2. 如何降低发送者和接收者的耦合度?
  3. 如何让Priority高的接收者先接到数据?
  4. 如何做到load balance?有效均衡接收者的负载?
  5. 如何有效的将数据发送到相关的接收者?也就是说将接收者subscribe 不同的数据,如何做有效的filter
  6. 如何做到可扩展,甚至将这个通信模块发到cluster上?
  7. 如何保证接收者接收到了完整,正确的数据?

RabbitMQ应用场景

消息机制,可以使软件应用,支持连接和大规模化。一个应用通过彼此连接的方式,可以作为一个大的应用的组件或者用户设备和信息中心。消息机制通过分离发送数据端和接收数据端,达到系统解藕,以及异步化。

以下场景你可以使用消息机制:

  1. 数据传输
  2. 非阻塞的操作,异步执行过程
  3. 推送通知
  4. 使用发布/订阅机制
  5. 使用一个工作队列

RabbitMQ实现了ANMQP标准,是一个消息机制的代理人-一个中间人。她是一个应用按照统一的平台来收发消息,并且你的消息会在一个安全的地方存放,除非消息被接收者消费。

RabbitMQ特性

  1. 可靠性(Reliability):RabbitMQ通过数据持久化,传输ack,发送确认,高可用的特性来保证她的高可靠性。
  2. 可集群(Clustering):通过一个逻辑中间人的形式,许多RabbitMQ的服务在同一的网络可以实现集群。
  3. 灵活路由(Flexible Routing):消息到达消息队列之前可以通过exchanges实现路由,RabbitMQ针对传统的路由逻辑类型,内置了几种消息exchanges类型。处理复杂的路由你可以把这些exhchange绑定使用,甚至可以自己写exchange类型,以插件的方式使用。
  4. 可联盟(Federation):For servers that need to be more loosely and unreliably connected than clustering allows,RabbitMQ提供了联盟模式。
  5. 高可用的队列(Highly Available Queues):队列能在集群中跨机器镜像,从而保证即使一些设备故障,你的信息还是安全的。
  6. 多协议支持(Multi-protocol):提供多协议支持
  7. 多客户端支持(Many Clients): 提供多种语言的客户端支持
  8. 可视化管理(Management UI):提供了简单易用的可视化管理界面管理你的RabbitMQ
  9. 可追踪(Tracing):如果你的消息系统出现异常,你可以通过轨迹记录查出问题所在
  10. 插件支持(Plugin System):RabbitMQ提供了许多的插件来按照你自己的方式扩展她。

RabbitMQ架构

RabbitMQ架构.png

消息被发送者发送到exchange上,然后exchange通过规则(bindings)将消息copy到相应的队列,接下来AMQP代理者将消息发送到订阅队列的消费者上,或者主动从自己需要的消息队列上拉消息。

当发送一个消息时,发送者会指定一些信息的属性(消息元数据)。一些消息元数据会被代理人(broker)使用,然后剩下来的是对代理人完全透明的(completely opaque),这些只有接收消息的应用才能使用。

网络是不稳定的,并且应用可能传递消息失败,因此AMQP模型引入了消息确认(message acknowledgements)的概念。当一个消费者接到一个消息,消费者通知代理人,或者自动的,或者一会有应用开发者去选择的通知代理人。代理人通过确认消息已被使用,来从消息队列中完全移掉此消息。

某些情况,例如当一个消息不能路由到一个消息队列,消息将会返回给消息发送者,删掉,或者代理人实现了扩展,把消息放到一个称之为“死信队列”(dead letter queue)的地方。消息发送者可以通过使用某些确定的参数来决定怎么处理这些情况。

Queues, exchanges和bindings 都是作为AMQP实体被集体引入进来的概念.

AMQP是一个可程控的协议

AMQP 0-9-1是一个在AMQP实体和路由场景的应用中,由应用自己定义的,而不是代理人管理者(broker)定义的。因此这样的需求使得它包括了定义队列和定义交换中心(exchange),定义他们之间的绑定关系(bindings),订阅队列等操作。

这是的应用开发者许多的自由,但与此同时考虑操作的冲突。实践中发现,定义的冲突经常是由于缺失配置引起的。

应用定义她们需要的AMQP实体,定义必要的路由场景,并且可能的选择删除那些不再使用的AMQP实体。

Exchanges和Exchange的类型

Exchange是当消息发送时的AMQP的实体,她获取发送者的消息,并且将消息路由到0个或者多个队列。使用怎样的路由算法,通过exchange的类型和bindings的规则决定,下面是一些基本的exchange类型:

名字 默认的指定名字
直接交换器(Direct exchange) (Empty string)和amq.direct
扇出交换器(Fanout exchange) amq.fanout
主题订阅交换器(Topic exchange) amq.topic
头交换器(Header exchange) amq.match(和amq.headers in RabbitMQ)

除了有这些交换器类型,交换器还有许多的属性,最重要的有以下这些:

  • 名字(Name)
  • 持久性(Durability):broker重启时,交换器还存活着
  • 自动删除(Auto-delete):当队列已经全部使用完,交换器自己删除
  • 参数(Arguments):这些代理人要使用

默认交换器

她是直接交换器,他有一个特别的属性使得她针对于简单的应用十分有用:每一个创建的队列是自动绑定一个和队列名字一样的路由key。例如:当你用“search-indexing-online”的名字定义了一个队列,AMQP代理者将使用“search-indexing-online”作为路由key绑定默认的交换器。因此一个消息使用这个路由key发送到默认的交换器,他将被存储到名字为“search-indexing-online”的队列。也就是说,直接交换器给人一种直接将消息发送到消息队列的感觉,虽然技术上不是这样实现的。

直接交换器

她是一种通过路由key将消息传递到队列中的一种交换器。她是单播传递信息的理想选择,尽管他也可以多播。

工作的机制
  1. 一个队列通过路由key K绑定在交换器上
  2. 当一个新的携带路由key R的消息到达直接交换器上,如果K = R,她将信息传递
使用场景

她经常使用在多个作业者(相同应用的实现)之间以轮循的方式分发任务。当这样使用的时候,理解在AMQP中负载均衡发生在消费者中而不是队列中是很重要的!

怎样生动的表示

直接交换路由

扇出交换器

她直接投递消息到所有绑定在她身上的队列,并且忽略路由key。她是广播消息的理想选择。

工作的机制
  1. N个队列绑定在某个扇出交换器上
  2. 当一个消息发送到这个交换器上,这个消息将被投递到这N个队列上
使用场景
  1. 大规模的多个在线玩家的游戏可以用它来更新积分榜或者其它的全局事件
  2. 体育新闻网站可以用它来发布分数给所有的手机客户端,几乎是实时的
  3. 分布式系统可以用它来广播各种状态和配置信息
  4. 群聊中可以用它来发布信息给所有参与者(尽管AMQP协议没有对这一块的规定,所以这种场景下,使用即时通信协议(XMPP)可能是最好的选择)
怎样生动的表示

fanout交换路由

主题交换器

她通过匹配一个路由key或者路由key的正则表达式,来讲消息发送到绑定在此交换器上的一个队列上。她通常用来实现各种多变的发布和订阅关系。她通常使用多播方式投递信息。她的使用场景很广,任何一个涉及到多个消费者和应用,并且她们要自己选择消息主题去接收消息的问题,都可以考虑使用主题交换器。

使用场景
  1. 分布数据与特定的地理位置,例如,销售点
  2. 多个工作者处理的后台任务,每一个工作者处理特定一系列任务能力
  3. 股票价格的更新(也可以更新某一类财政数据)
  4. 按照某个类别和标签更新新闻(例如:仅仅是特定的运动或者运动对)
  5. 在云上精心编排的各种服务
  6. 分布式架构/特定的系统 的软件,当每一个构建者只能兼容一个架构或者某一个系统的构建或者打包

头交换器

她是设计用来投递许多属性以头信息的方式更容易投递。而不是以路由key的方式。头交换器忽略路由key属性。取而代之的是,使用头信息里的属性。当头信息里header的值等于绑定的值,认为信息符合。

这可能绑定一个队列到一个头交换器使用多个header匹配。这样的话代理者就需要额外的信息来确定是要全部匹配还是当个匹配,有一个叫“x-match”的属性,如果你设置为any,就仅仅需要一个header值被匹配就可以了。当这个设置为all,则需要所有的header都被匹配才可以。

头交换器可以看作为直接交换器在类固醇上。因为他是靠头信息值来路由的,这可以认为是没有使用空值作为路由key的直接交换器。例如它可以是一个整形值或者一个hash值。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!