AMQP,即 高级消息队列协议(Advanced Message Queuing Protocol),是一个消息中间件应用层协议,用于组件之间的解耦,来提供 统一消息服务。主要功能是 排序消息,路由消息(包括点对点和订阅-发布),保证消息的可靠性和安全性。 遵循AMPQ协议的客户端,都能通过 消息中间件 相互通信。这样 客户端 就可以采用不同的开发语言实现,彼此无强依赖关系,降低客户端复杂性,提高开发效率也利于后期维护。
AMQP 的模型架构如下:
最左端和最右端,publisher(消息生产者),consumer(消息消费者) 都是客户端左上方灰色方框为 message消息结构(交换器名exchange_name,路由键rountingKey)中间红色方框为 message broker(消息中间件),如 rabbitMQ,kafka客户端通过 tcp连接,建立 connection 来进行通信 下面介绍AMQP模型的概念: 1.'pubilsher':消息生产者,生产消息并投送到指定的交换器上。 2.'consumer':消息消费者,从对应的队列中取出消息消费。 1)当 autoAck 为 true 时,消息发送出去后就认为消费成功,而不管消费者是 否真正消费到这些消息。当channel因意外而关闭,或者消费者在消费过程之 中意外宕机时,会丢失对应的消息。因此这种模式可以提高吞吐量,但存 在数据丢失的风险。 2)当 autoAck 为 false 时,consumer在数据处理完成后需要返回确认信息, 只有broker收到确认消费信息后,才认为这条消息已经被成功处理。 这可以保证数据的可靠性投递,但会降低系统的吞吐量。 3.'message':消息,由消息头和消息体组成。消息头存储与消息相关的元数据, 如交换器名字(exchange_name),路由键(rountingKey)和可选配置(properties), 消息体为实际需要传递的数据。 4.'message_broker':消息中间件,如rabbitMQ,kafka。 5.'virtual_host':虚拟主机,类似于linux的namespace,实现用户资源的隔离 当 broker 有多个用户时,可以划分出多个 vhost,每个vhost类似于小型的broker, 拥有独立的交换器,队列和绑定关系。用户根据不同的应用场景选择vhost。 6.'exchange':交换器,message到达 broker 的第一站。 负责接收publisher的消息并根据绑定关系,将消息路由到到一个或多个queue中 1)当mandatory为true时,如果根据分发规则找不到符合条件的queue,会将消息返回给publisher 2)当mandatory为false时,如果根据绑定关系找不到符合条件的queue,会直接丢弃该message 7.'bindingKey':绑定键,exchange和queue通过bindingKey建立绑定关系。 另外还有 'rountingKey'。当publisher将message发送给exchange时,一般会 指定一个 rountingKey,用来指定这个message的路由规则。当rountingKey和 bindingKey基于规则匹配时,消息被路由响应的queue中 8.'queue':消息队列。存储路由过来的message,一个queue可以被多个 consumer订阅,此时queue会通过轮询(round-robin)方式分发message,即 每条message只会发送给一个consumer,不会出现同一个message被多个 consumer重复消费的情况。 9.'connection':用来传递消息的tcp连接 10.'channel':信道。是在connection内部采用 IO多路复用建立的逻辑连接, 每个chanel拥有独立的channelID,保证channel之间的隔离性,类似于在同一个 tcp连接中建立更小的tcp独立连接,每次断开连接,断开的是channel连接, 最外层的tcp连接并不会断开,一直在被复用,极大减少了tcp连接的开销。rabbitMQ是AMQP协议的一个开源实现。架构模型同样可以用以下的图来表示:
rabbitMQ具有以下特点: 1. 可靠性,使用一些机制,如持久化,发布确认,传输确认等保持可靠性 2. 灵活的路由,提供了多种6工作模式满足各种业务需求 3. 集群性,多个 rabbitMQ 服务器可以组成一个集群,形成一个逻辑 broker 4. 高可用,queue可以在集群上进行镜像,使得部分节点出问题仍能保持可用 5. 多种协议,支持多种消息队列协议,如stomp,mqtt等等 6. 多语言客户端,几乎支持所有常用语言,如java,ruby,golang等等 7. 管理界面,提供了一个易用的用户界面,方便监控和管理 8. 跟踪机制,如果消息异常,使用者可以找出发生了什么问题 9. 插件机制,提供了许多插件来扩展,也可以编写自己的插件如上图,simple模式,单个publisher,单个queue,单个consumer
如上图,work模式 多个consumer共用一个queue的message 此种模式下,rabbitMQ会自动做负载均衡,将消息轮询发送给各个消费者,即一个消息只能被一个消费者获取
如上图,publish / subscribe 发布订阅模式(广播模式) 相对前2种模式,多了一个exchange (type为fanout),message先发送到exchange,exchange再分别发送到对应的所有queue。而consumer订阅自己的queue,在自己订阅的queue上消费message。
示例应用场景,如下图示:
比如 网上购物,下单支付成功后,通知用户的方式有许多种,app推送,短信,email 等等。 message到来后被exchange发送到3个queue(app推送q,短信q,email_q) 之后 app推送服务,短信通知服务,email通知服务 从各自订阅的queue获取消息,通知用户支付成功
如上图示,exchange类型设定为direct 此时 message中的rountingKey 和 exchange中的bindingKey匹配,两者相等则发送对应的queue中,如果匹配不到bindingKey,则丢弃该message。
示例应用场景,如下图示:
比如服务产生的日志,日志有许多类型,error,info,debuf等类型的日志,而我们的需求只想要将 error 类型的日志写入磁盘,就可以用routing模式,将error日志路由到error queue,再由相应的 写入磁盘服务获取message,写入磁盘
如上图示,exchange类型为topic,相对于第4种模式,相同点是都根据 rountingKey 匹配,不同点是 topic 模式支持模糊匹配。
应用场景,比如不同运营商的手机号码处理不同,可以根据手机号码的前几位去做区分,如'185','139'等等