RabbitQM入门概念(一)

原创
2016/06/19 16:46
阅读数 165

一、RabbitMQ基本概念

rabbitMQ是什么

AMQP简介

说到rabbitMQ,就不得不提下AMQP(advanced Message Queuing Protocol)高级消息队列协议

AMQP是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件而设计的。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。

Alt text 上图即AMQP消息队列的模型。

  • Publisher即消息的生产者,消息生产者负责生产消息并发布到消息队列中。

  • Consumer即消息的消费者,消费者负责从消息队列中取出消息,并对消息做相应的处理。

  • 中间大矩形中的所有可以理解成一个消息队列服务器。

rabbitMQ和AMQP的关系。

AMQP是一个协议标准,一个规范,rabbitMQ是具体的实现。

##为什么要使用消息队列。 刚接触消息队列的人可能会有一些误解。

  • 以为消息队列是用来提高系统性能,加速消息转发。其实不然,如果加速消息转发,直接自己在内存中写一个queue,把消息的生产者和消费者合在一起,没了持久化、网络传,消息转发岂不是更快。
  • 以为消息队列,就是一个数据源,作为下一级输入的数据源,存放中间结果用的。这当然没错,但是如果纯作存放中间结果用,你为什么不直接用数据库,或者用redis,说不定性能还更佳。

前面也说了,amqp最大的特点是解耦,不同系统,不同编程语言之间可以通行协同工作。其次就可拓展的灵活性,因为消息队列解耦了你的处理过程,把消息发布与消息处理分离。那消息分发的灵活性,消息处理频率的灵活性即可很好的调节。

####总结使用消息队列的好处如下:

1、解耦。在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息队列在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。


2、冗余。有时在处理数据的时候处理过程会失败。除非数据被持久化,否则将永远丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。在被许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理过程明确的指出该消息已经被处理完毕,确保你的数据被安全的保存直到你使用完毕。


3、扩展性。因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的;只要另外增加处理过程即可。不需要改变代码、不需要调节参数。扩展就像调大电力按钮一样简单。


4、灵活性 & 峰值处理能力。当你的应用上了Hacker News的首页,你将发现访问流量攀升到一个不同寻常的水平。在访问量剧增的情况下,你的应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住增长的访问压力,而不是因为超出负荷的请求而完全崩溃。请查看我们关于峰值处理能力的博客文章了解更多此方面的信息。


5、可恢复性。当体系的一部分组件失效,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。而这种允许重试或者延后处理请求的能力通常是造就一个略感不便的用户和一个沮丧透顶的用户之间的区别。


6、送达保证。消息队列提供的冗余机制保证了消息能被实际的处理,只要一个进程读取了该队列即可。在此基础上,IronMQ提供了一个"只送达一次"保证。无论有多少进程在从队列中领取数据,每一个消息只能被处理一次。这之所以成为可能,是因为获取一个消息只是"预定"了这个消息,暂时把它移出了队列。除非客户端明确的表示已经处理完了这个消息,否则这个消息会被放回队列中去,在一段可配置的时间之后可再次被处理。


7、异步通信。很多时候,你不想也不需要立即处理消息。消息队列提供了异步处理机制,允许你把一个消息放入队列,但并不立即处理它。你想向队列中放入多少消息就放多少,然后在你乐意的时候再去处理它们


8、排序保证。在许多情况下,数据处理的顺序都很重要。消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。IronMO保证消息浆糊通过FIFO(先进先出)的顺序来处理,因此消息在队列中的位置就是从队列中检索他们的位置


9、缓冲。在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行--写入队列的处理会尽可能的快速,而不受从队列读的预备处理的约束。该缓冲有助于控制和优化数据流经过系统的速度。


10、 理解数据流。在一个分布式系统里,要得到一个关于用户操作会用多长时间及其原因的总体印象,是个巨大的挑战。消息系列通过消息被处理的频率,来方便的辅助确定那些表现不佳的处理过程或领域,这些地方的数据流都不够优化。


AMQP中几个重要的概念、对象

消息队列运作可以理解成收发快递的运作。 消息发布者相当于发件人;消息的消费者相当于收件人;整个快递公司相当于消息队列的服务器;快递员相当消息队列服务器中的消息队列。

####AMQP中的几个对象如下:

1.publisher。 消息的发布者。发件人
2.Consumer。 消息的消费者。 收件人
3.Exchange。 交换机。这儿可以理解为快递点,负责把消息(快递)分发到对应的queue(快递员)中。
5.Queue。  用来存储消息的队列(快递员)。

####AMQP中的几个概念

1.Binding。 绑定,是把Exchange和queue之联系起来。binding key就是联系的规则。这儿可以把Exchange理解为快递点,queue可以理解为快递员。binding就是快递点和快递员之间的协商,快递员负责的哪一片区域。binding key可以理解为快递员负责的区域。
2.binding key。 Exchange和queue之间的连接规则,快递员负责的区域。
3.routing key。消息生产者生产的消息中携带的Exchange到queue之间的规则。这儿可以理解为快递中的具体地址,是属于每一个消息(快递包裹)的属性。binding key是Exchange和queue之间的关系。基本上binding key和routing key的作用是相同,没多大却别。
4.Message acknowledgment。 消息确认回执。即消费者收到消息后,给消息队列服务器的确认回执,类似于快递回执单。
5.Message durability。 消息的持久化,在系统宕机后,可以恢复没出来完的消息。
6.Prefetch count。预取消息。在多个消费者共享一个队列的案例中,明确指定在收到下一个确认回执前每个消费者一次可以接受多少条消息是非常有用的。

二、AMQP中的对象及概念的详细介绍

Exchange和Exchange Type

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

Name(交换机类型) Default pre-declared names(预声明的默认名称) 说明
Direct exchange(直连交换机) (Empty string) and amq.direct routing key必须和binding key完全匹配
Fanout exchange(扇型交换机) amq.fanout binding key无效,Exchange会把消息发送到所有bind到该Exchange的queue
Topic exchange(主题交换机) amq.topic binding key与routing key只需要一个匹配上,即会转发消息
Headers exchange(头交换机) amq.match (and amq.headers in RabbitMQ) 使用消息的属性进行匹配,binding key不起作用
除交换机类型外,在声明交换机时还可以附带许多其他的属性,其中最重要的几个分别是:
  • Name
  • Durability (消息代理重启后,交换机是否还存在)
  • Auto-delete (当所有与之绑定的消息队列都完成了对此交换机的使用后,删掉它)
  • Arguments(依赖代理本身)

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


默认交换机

默认交换机(default exchange)实际上是一个由消息代理预先声明好的没有名字(名字为空字符串)的直连交换机(direct exchange)。它有一个特殊的属性使得它对于简单应用特别有用处:那就是每个新建队列(queue)都会自动绑定到默认交换机上,绑定的键(binding key)名称与队列名称相同。默认交换机可以理解成一个特殊的直连交换机。

直连交换机

直连型交换机(direct exchange)是根据消息携带的路由键(routing key)将消息投递给对应队列的。直连交换机用来处理消息的单播路由(unicast routing)(尽管它也可以处理多播路由)。下边介绍它是如何工作的:

  • 将一个队列绑定到某个交换机上,同时赋予该绑定一个路由键(routing key)
  • 当一个携带着路由键为R的消息被发送给直连交换机时,交换机会把它路由给绑定值同样为R的队列。 直连交换机经常用来循环分发任务给多个工作者(workers)。当这样做的时候,我们需要明白一点,在AMQP 0-9-1中,消息的负载均衡是发生在消费者(consumer)之间的,而不是队列(queue)之间。

直连型交换机图例:

Alt text

扇型交换机

扇型交换机(funout exchange)将消息路由给绑定到它身上的所有队列,而不理会绑定的路由键。如果N个队列绑定到某个扇型交换机上,当有消息发送给此扇型交换机时,交换机会将消息的拷贝分别发送给这所有的N个队列。扇型用来交换机处理消息的广播路由(broadcast routing)。

因为扇型交换机投递消息的拷贝到所有绑定到它的队列,所以他的应用案例都极其相似:

  • 大规模多用户在线(MMO)游戏可以使用它来处理排行榜更新等全局事件
  • 体育新闻网站可以用它来近乎实时地将比分更新分发给移动客户端
  • 分发系统使用它来广播各种状态和配置更新
  • 在群聊的时候,它被用来分发消息给参与群聊的用户。(AMQP没有内置presence的概念,因此XMPP可能会是个更好的选择)

扇型交换机图例:

Alt text

头交换机

有时消息的路由操作会涉及到多个属性,此时使用消息头就比用路由键更容易表达,头交换机(headers exchange)就是为此而生的。头交换机使用多个消息属性来代替路由键建立路由规则。通过判断消息头的值能否与指定的绑定相匹配来确立路由规则。

我们可以绑定一个队列到头交换机上,并给他们之间的绑定使用多个用于匹配的头(header)。这个案例中,消息代理得从应用开发者那儿取到更多一段信息,换句话说,它需要考虑某条消息(message)是需要部分匹配还是全部匹配。上边说的“更多一段消息”就是"x-match"参数。当"x-match"设置为“any”时,消息头的任意一个值被匹配就可以满足条件,而当"x-match"设置为“all”的时候,就需要消息头的所有值都匹配成功。

头交换机可以视为直连交换机的另一种表现形式。头交换机能够像直连交换机一样工作,不同之处在于头交换机的路由规则是建立在头属性值之上,而不是路由键。路由键必须是一个字符串,而头属性值则没有这个约束,它们甚至可以是整数或者哈希值(字典)等。

消息队列

消息队列是用来缓存消息。 由Exchange把消息推送到queue中。

队列持久化

持久化队列(Durable queues)会被存储在磁盘上,当消息代理(broker)重启的时候,它依旧存在。没有被持久化的队列称作暂存队列(Transient queues)。并不是所有的场景和案例都需要将队列持久化。

持久化的队列并不会使得路由到它的消息也具有持久性。倘若消息代理挂掉了,重新启动,那么在重启的过程中持久化队列会被重新声明,无论怎样,只有经过持久化的消息才能被重新恢复。

绑定

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

  • 队列(queue):快递员,快递员手中会有多个包裹(消息)。
  • 交换机(exchange):快递点,快递点负责把各个包裹分派到不同快递员中。
  • 绑定(binding):快递员和快递点之间的协商,各个快递员负责的区域。
展开阅读全文
打赏
0
9 收藏
分享
加载中
更多评论
打赏
0 评论
9 收藏
0
分享
返回顶部
顶部