MQ学习小记

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

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

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

一般的消息队列是基于生产者-消费者模型。用于实时性要求并不是那么高、异步通信的场景。

AMQP模型

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

AMPQ的消息模型示意

运作过程

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

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

名词解释

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

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

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

一个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的工作原理:

从上图看,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"。
  • Exchange把此消息转发到消息队列op_queue
  • 消息队列op_queue把消息推送给服务端,服务端执行此RPC调用对应的任务。执行结束后,服务端把相应结果发送给消息队列,指明routing key为"res_queue"
  • Exchange 把此消息转发到消息队列res_queue
  • 客户端从消息队列res_queue中获取响应。

小结

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

扩展参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,668评论 18 139
  • 来源 RabbitMQ是用Erlang实现的一个高并发高可靠AMQP消息队列服务器。支持消息的持久化、事务、拥塞控...
    jiangmo阅读 10,361评论 2 34
  • RabbitMQ详解 本文地址:http://www.host900.com/index.php/articles...
    嘉加家佳七阅读 2,516评论 0 9
  • 1. 历史 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的...
    高广超阅读 6,096评论 3 51
  • 姓名:王方河 公司:宁波大发化纤有限公司 宁波盛和塾《六项精进》235期学员。 【日精进打卡第16天】 【知~学习...
    北辕南辙阅读 114评论 0 0