
点击右侧关注,大数据开发领域最强公众号!
大数据真好玩
点击右侧关注,大数据真好玩!
前言
自从去年做了不少流式系统(Flink也好,Spark Streaming也好)对接RabbitMQ的实时作业。之前一直都在Kafka的领域里摸爬滚打,对RabbitMQ只是有浅薄的了解而已。随着自己逐渐把RabbitMQ的官方文档大致翻完,了解到它是高级消息队列协议(Advanced Message Queuing Protocol, AMQP)的一种标准实现。也就是说,搞清楚AMQP是掌握好RabbitMQ哲学的基础。
当前AMQP的最新版本为1.0,而主要使用的(也是RabbitMQ实现的)版本为0-9-1。这两个版本之间的差别非常大,本文抄录的是AMQP 0-9-1的部分细节。
通俗地讲,AMQP是一个专门为消息中间件设计的、开放标准的应用层协议,它规定了消息系统中三大组件——消息服务器/代理节点(server/broker)、生产者/发布者(producer/publisher)、消费者/订阅者(consumer/subscriber)之间的通信规范,以及代理节点的设计规范等。
AMQP采用的模型就叫做高级消息队列模型,即AMQ模型,它的组成可以用下面的简图来表示。

下面就图中出现的一些名词进行解释。
接下来对交换器和队列这两个比较重要的组件进行介绍,顺便牵出一些其他的东西。
交换器在AMQP实体中负责消息路由。它的路由目的地除了由用户设置的绑定规则来决定之外,还与交换器的类型有关。AMQP定义了几种默认的交换器。
直连交换器非常简单,它检查绑定关键字(binding key)与路由关键字(routing key),只要两者相同,即进行投递。

扇出交换器比直连交换器更简单,它会直接将消息路由到所有与它绑定的队列中。


根据AMQP的规定,交换器的几个重要属性有:
如果交换器无法将消息路由到队列该怎么办呢?AMQP给出了几种解决方法,一是直接丢弃,二是返还给生产者,三是放入死信队列中等待进一步处理。这由消息头部中的属性来决定。
队列相对而言比较简单,它的主要功能就是存储要被消费的消息。队列也有一些重要的属性,如下:
需要注意,如果一个队列是持久的,那么只是代表重启之后这个队列不用重新创建而已,但其中的消息还是有可能被删除。只有那些被标记为persistent的消息才不会被删除。
AMQP规范下的队列和消费者都同时支持推模式和拉模式消费。前者即AMQP实体将消息投递到消费者,后者即消费者主动地从队列中获取消息。无论推模式还是拉模式,每个消费者也有一个标识,称为tag。
在队列中的消息投递出去之后,消费者需要告诉代理节点自己是否收到了它,因此会涉及消息确认(ack)的问题。AMQP默认定义了两种ack机制:
除了ack之外,消费者在处理时有可能会出现问题,或认为此消息非法,因此也会出现拒绝消息(reject)的情况。此时代理节点可以销毁这条消息,也可以重新将它放入队列并投递给另一个消费者。
说了这么多,那么Kafka和AMQP有什么关系呢?答案是没关系。
也就是说,Kafka不是消息队列。按官方说法,Kafka是一个流式处理平台(stream processing platform)。Kafka在设计之初是为了支持高吞吐量的日志处理的,只不过它恰好也可以实现消息队列的大部分功能而已。Kafka所用的“黑科技”(如零拷贝/内存映射,以及对page cache的利用)都是脱离标准消息队列的设计范畴的,所以不能简单地认为Kafka比RabbitMQ等符合AMQP的消息队列更优。例如,RabbitMQ支持死信队列、延迟队列、优先队列、多租户、推模式消费等,Kafka统统不支持。


版权声明:
本文为大数据技术与架构整理,原作者独家授权。未经原作者允许转载追究侵权责任。
编辑|冷眼丶
微信公众号|import_bigdata
欢迎点赞+收藏+转发朋友圈素质三连