玩转RabbitMQ之三:理解消息通信中的概念

一、消息投递

        为了对消息投递有更深刻的理解,先说说传统的“快餐车模式”,传统的BS模式,Browser(浏览器)发起请求,Server(服务器)处理相应请求,客户端请求的数据来源于服务器端,就像一个顾客向快餐车发起购买快餐的请求,快餐来源于快餐车。

"快餐车模式"

       对于消息投递,现实生活中向邮局投递信件就是一个非常贴切的类比,你写了一封信,投递到邮局的邮箱里去,邮递员定期从邮箱里取走邮件,然后根据上面写的地址投递到你的女朋友手上,这个过程邮局没有对你的信件做什么特别的处理,你的女朋友收到信之后会怎么处理也与邮局无关,这里邮局只是起到邮件传递的作用。

消息投递

       同样的,在消息投递中,RabbitMQ既不产生消息,也不处理消息,只是根据消息生产者设定的“地址”(绑定关系),将消息投递给相应的消费者“处理”(消费),RabbitMQ既不是消息的源点,也不是消息的终点,它其实是一个中转站、路由器。

二、生产者、消费者

       生产者(producer)产生消息,将其发到RabbitMQ代理服务器,消息上带有标签(简单地说就是投递地址),RabbitMQ根据标签将消息投递给相应的消费者(consumer)。这种通信方式是一种“发后即忘”(fire-and-forget)的单向方式,生产者虽然给消息设置了投递地址/规则,但是不一定知道最终消息会被哪个消费者消费,这跟邮件投递略有不同,比如生产者设置了路由键是aaa.bbb,那么消息可能被消费路由键为aaa.*或*.bbb的消费者消费,但生产者不关心消息最终去了哪里,发完就不管了,所以叫“发后即忘”。

"发后即忘"模式

        在玩转RabbitMQ之二:RabbitMQ简史中谈到了发布订阅(PubSub)模式,消费者向MQ订阅消息,当符合订阅规则的消息到达MQ时,MQ就会投递给其中一个消费者,但消费者不会知道是谁产生的消息,也不知道生产者消息的具体路由规则,消费者只是知道收到了符合它设定规则的消息的内容,生产者发布消息时包含了路由标签,但到达消费者时标签已被剥离。

        从下图,可以清楚看到生产者到消费者的消息流。

从生产者到消费者的消息流

三、信道

       应用程序要连接到RabbitMQ代理服务器,必须先建立一条TCP连接,由于TCP连接的建立代价很大,也比较消耗资源,如果所有的消息通信都使用TCP连接,计算机无法满足高并发的消息连接需求,为此,AMQP提出了一个信道的概念,一个AMQP连接(TCP)内可以创建多个信道,并且是无限制的,消息需要发布或消费时则动态建立信道跟MQ通信即可,这节省了宝贵的TCP连接资源,也提高了消息并发处理能力。

AMQP Channel

四、AMQP栈

        AMQP协议规定了路由消息必须有三个组成部分:交换器、绑定、队列,如下图所示:

AMQP栈

       生产者将消息发布到交换器,交换器根据绑定规则,将消息分发到对应的队列,消息出队后被消费者消费。

1、交换器和绑定

       交换器是一个虚拟的用来接收、投递消息的中间构件。生产者将消息发布到交换器上,并声明绑定的路由规则,然后交换器根据绑定路由规则,将消息投递到满足绑定路由规则的队列上。

       举个例子,你写信给女朋友Alice,信件上写明要投递到某个地址上面去,然后将信件投递到邮箱,接着邮递员从邮箱中取邮件,根据你填写的地址将信件发到Alice的家中,这里邮箱、快递员、信件上的地址就组成了交换器的效果,邮箱负责接收信件、快递员负责发信件、信件地址是投递信件的规则。

       当然,绑定规则跟信件地址并不是完全相等的关系,参考上面的“发后即忘”模型图。

       RabbitMQ中有三种常用的交换器,分别是direct、fanout、topic,还有一种headers交换器,允许匹配AMQP消息的header而非路由键,但其性能差因此几乎不会用到。

(1)direct交换器

        direct交换器是直接路由键匹配,如图所示:

direct交换器

        RabbitMQ默认实现了一个名字为空字符串的direct交换器,当声明一个队列时,默认会绑定到这个默认的交换器。

(2)fanout交换器

        fanout交换器会将收到的消息广播到绑定的队列上,比如应用程序中A模块完成之后必须触发B、C、D模块,并且B、C、D之前是并发的没有程序耦合关系,则适合对B、C、D分别声明一条队列来实现与A模块的关联,通过MQ,A模块无需显式地去调用BCD,实现了程序的解耦,这也是MQ存在的意义之一。

fanout交换器

(3)topic交换器

        topic交换器是RabbitMQ中最灵活的交换器,由于队列支持对绑定关系进行模糊匹配,因此能够实现多种复杂的应用场景需求,下面以日志搜集为例,实现对不同日志级别维度的日志进行收集,如图所示:

topic交换器

五、虚拟主机与隔离

        RabbitMQ默认的虚拟主机是: "/",vhost是AMQP的概念,每个vhost都有自己的队列、交换器和绑定,还有独立的权限机制,vhost存在的意义在于一个RabbitMQ服务器为多个应用程序提供队列服务时通过使用不同的vhost实现互相隔离,避免不同应用程序的队列服务互相干扰。

        RabbitMQ里创建用户时,通常会被指派至少一个vhost,并且只能访问被指派vhost内的队列、交换器和绑定。


六、RabbitMQ的持久化策略

1、持久化消息

       当RabbitMQ服务器发生宕机或者需要重启时,默认情况下消息、队列、交换器都会消失,为了避免消息、队列、交换器相关的数据丢失,需要将消息、交换器、队列都设置为持久化(durable属性)。

(1)消息持久化的原理

        对交换器和队列来说,当被设置为持久化时其相关数据会在磁盘中做备份,这样RabbitMQ服务器重启时会从磁盘中读取备份的数据恢复重建交换器和队列;对于消息来说,要实现持久化,除了将 “投递模式” (delivery mode)设为2之外,还需要将消息发布到持久化的交换器中并且到达持久化队列中才完成持久化存储,其他情况下的消息为无法应对服务器宕机和重启的非持久化。

        当消息经过持久化交换器到达持久化队列是,RabbitMQ会将消息写入磁盘上的持久化日志文件,当持久化队列中的持久化消息被消费时,RabbitMQ会将持久化日志中这条消息标记为等待垃圾回收,然后在某个时间点RabbitMQ将其从持久化日志中删除。

(2)消息持久化的缺点

        消耗性能,大幅度降低MQ服务器吞吐率;在MQ内建集群中工作得并不好,一旦某个集群节点宕机,这个节点上的队列不可用,直到节点恢复,而且出于系统容量和性能考虑,持久化消息不会在集群其他节点上备份,这导致未出队消息无法被消费,未写入到磁盘的消息也会丢失。

2、AMQP事务

        为了弥补消息丢失的风险,产生了AMQP事务,简单地说就是将消息的发布和提交到磁盘上视为一个整体事务(要么都成功,否则视为失败),如果你了解数据库中事务的概念,想必不难理解。

缺点

        大幅度降低系统消息吞吐量;由于消息发布和提交磁盘存储视为一个事务,会导致生产者应用程序发生同步。

3、发送方确认模式

        生产者发布消息时首先要将信道设置成confirm模式,当消息成功写入磁盘后,MQ会向生产者发送一条确认消息,生产者收到成功的确认消息才认定为消息发布成功,当生产者受到确认消息时就会触发回调处理确认消息。

优点

        既保持了消息发布和写入磁盘的事务一致性,又通过异步实现避免性能瓶颈。

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,649评论 18 139
  • 来源 RabbitMQ是用Erlang实现的一个高并发高可靠AMQP消息队列服务器。支持消息的持久化、事务、拥塞控...
    jiangmo阅读 10,357评论 2 34
  • RabbitMQ 简介 MQ 消息队列,上承生产者,下接消费者。从生产者侧获取消息,然后将消息转发给消费者。由此可...
    2205阅读 3,493评论 1 11
  • http://liuxing.info/2017/06/30/Spring%20AMQP%E4%B8%AD%E6%...
    sherlock_6981阅读 15,906评论 2 11
  • 利用RabbitMQ集群横向扩展能力,均衡流量压力,让消息集群的秒级服务能力达到百万,Google曾做过此类实验;...
    有货技术阅读 3,463评论 0 1