MQ学习小记

“消息队列”是在消息的传输过程当中保存消息的容器。算法

“消息”是在两台计算机间传送的数据单位。消息能够很是简单,例如只包含文本字符串;也能够更复杂,可能包含嵌入对象。缓存

消息被发送到队列中。“消息队列”是在消息的传输过程当中保存消息的容器。消息队列管理器在将消息从它的源中继到它的目标时充当中间人。队列的主要目的是提供路由并保证消息的传递;若是发送消息时接收者不可用,消息队列会保留消息,直到能够成功地传递它。安全

通常的消息队列是基于生产者-消费者模型。用于实时性要求并非那么高、异步通讯的场景。服务器

AMQP模型

AMQP(AdvancedMessageQueuingProtocal,高级消息队列协议)是一个提供统一异步消息传递服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件而设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不一样产品、不一样开发语言等条件的限制。架构

AMPQ的消息模型示意

运做过程

左边的客户端向右边的客户发送消息,流程以下:异步

  1. 获取Connection(客户端到MQ服务器的TCP链路)
  2. 获取Channel(逻辑层的链路,基于Conncetion)
  3. 定义交换器、队列
  4. 使用一个RoutingKey将队列绑定到一个交换器
  5. 经过指定一个交换器和一个RoutingKey来消息发送到对应的队列上
  6. 接收方在接受时也是获取Connection,接着获取Channel,而后指定一个队列直接到它关心的队列上取消息,它对交换器、RoutingKey及如何绑定都不关心,到对应的对列上取消息就好了

名词解释

在该模型中,三个主要功能模块链接成一个处理链完成预期的功能:ui

  • exchange(交换器):接收发布应用程序发送的消息,并根据必定的规则将这些消息路由到“消息队列”。
  • message queue(消息队列):存储消息,直到这些消息被消费者安全处理完为止。
  • binding(绑定器):定义了exchange和message queue之间的关联,提供路由规则。

Exchange自己不保持消息,只是起到路由的做用,Exchange接收消息生产者(MessageProducer)发送的消息根据不一样的路由算法将消息发送往MessageQueue。MessageQueue会在消息不能被正常消费时缓存这些消息,具体的缓存策略由实现者决定,当MessageQueue与消息消费者(Messageconsumer)之间的链接通畅时,MessageQueue会将消息转发到consumer。spa

一个Broker(AMQP服务器)中会存在多个MessageQueue?Exchange怎样知道它要把消息发送到哪一个MessageQueue中去呢?图8-1中的Binding就是经过绑定Exchange与MessageQueue来解决这个问题。消息应用者(ClientApplication)控制Exchange与某个特定MessageQueue绑定,并将这个MessageQueue接受何种特定消息的条件绑定到Exchange,这个条件也叫Bindingkey或Criteria。AMQP协议的架构以下图示意。设计

AMQP架构图

该图(VirtualHost)用来指Exchange和MessageQueue组成的集合。它是一个虚拟概念,一个虚拟主机能够是一台服务器,还能够是由多台服务器组成的集群,还能够是一些虚拟机组成的集群,上面运行一些Exchange和MessageQueue。

下面详细解释一下AMQP的工做原理:3d

从上图看,Message是AMQP所操纵的基本单位,它由Producer产生,通过Broker被Consumer所消费。它的基本结构有两部分:Header和Body。Header是由Producer添加上的各类属性的集合,这些属性有:控制Message是否可被缓存,接收的Queue是哪一个,优先级是多少等。Body是真正须要传送的数据,它是对Broker不可见的二进制数据流,在传输过程当中不该该受到影响。

一个Exchange在与多个MessageQueue经过绑定后,Exchange中就会存在一个路由表,这个表中存储着每一个MessageQueue所须要消息的限制条件。Exchange就会检查它接收到的每一个Message的Header及Body信息,来决定将Message路由到哪一个Queue中去。每一个Message的Header中应该有个属性叫RoutingKey,它由Message发送者产生,提供给Exchange路由这条信息的标准。Exchange根据不一样路由算法有不一样有ExchangeType。

  1. Direct类型,须要BindingKey等于RoutingKey。也就是1对1模式。
  2. Topic类型,全部符合RoutingKey(能够是一个表达式)RoutingKey所绑定的队列能够接受消息。至关于经过RoutingKey进行了过滤。
  3. Fanout类型,忽略BindingKey和RoutingKey,消息传递到全部绑定的MessageQueue。即全部绑定此交换器的队列均可以接收消息,典型的订阅/发布模型。
  4. 也能够根据Message包含的某些属性来判断。

这些基础的路由算法由AMQP提供,固然ClientApplication也能够自定义各类本身的扩展路由算法。

当Exchange按照必定的路由算法把消息发到MessageQueue后,做为消息的存储和分发实体,MessageQueue会把消息缓存到内存或硬盘中,而且按照顺序把这些消息发给一个或者多个消息的消费者。

MQ在实际项目中的使用

openStack中的MQ

OpenStack遵循这样的设计原则:项目之间经过RESTful API进行通讯;项目内部,不一样服务进程之间的通讯,则必需要经过消息总线。这种设计思想保证了各个项目对外提供服务的接口能够被不一样类型的客户端高效支持,同时也保证了项目内部通讯接口的可扩展性和可靠性,以支持大规模的部署。

软件从最初的面向过程,面向对象,再到面向服务(SOA),要求咱们去考虑各个服务之间如何传递消息。借鉴硬件总线的概念,消息总线的模式被引入,顾名思义,一些服务向总线发送消息,其余服务从总线上获取消息。

OpenStack oslo.messageing库实现了如下两种方式来完成项目内部各服务进程之间的通讯:

远程过程调用(RPC,Remote Procedure Call)

经过远程过程调用,一个服务进程能够调用其余远程服务进程方法,而且有两种调用方式:call和cast。call 则是同步执行的,调用者会被阻塞直到结果返回;cast 则是异步执行,结果不会马上被返回,调用者也不会被阻塞,可是调用者须要利用其余方式查询此次远程调用的结果。

事件通知(Event Notification)

某个服务进程能够把事件通知发送到消息总线上,该消息总线上全部对此类事件感兴趣的服务进程,均可以得到此事件通知并进行一步的处理,处理的结果并不会返回给事件发送者。这种通讯方式,不但能够在同一个项目内部的各个服务进程之间发送通知,也能够实现跨项目之间的通知发送。Ceilometer就经过这种方式大量获取其余OpenStack项目的事件通知,从而进行计量和监控。

OpenStack中的通讯方式

AMQP

OpenStack中所支持的消息总线类型中,大部分都是基于AMQP的。前面已经提到过了,故不赘述。

基于AMPQ实现RPC

配图解释:

openStack设计与实现——基于AMPQ的RPC实现.jpg

  • 客户端发送一个请求消息给Exchange,指定routing key为"op_queue",同时指明一个消息队列名用来获取响应,图中为"res_queue",同时指明一个消息队列名用来获取响应。在图中为"res_queue"
  • Exchange把此消息转发到消息队列op_queue
  • 消息队列op_queue把消息推送给服务端,服务端执行此RPC调用对应的任务。执行结束后,服务端把相应结果发送给消息队列,指明routing key为"res_queue"
  • Exchange 把此消息转发到消息队列res_queue
  • 客户端从消息队列res_queue中获取响应。

小结

对于MQ中的概念进行了简单的介绍。以后还会进行必定的扩充——好比在一些常见应用中MQ的应用。

扩展参考

相关文章
相关标签/搜索