rabbitmq学习(一):AMQP协议,AMQP与rabbitmq的关系
前言
当学习完AMQP的基本概念后,可以到http://tryrabbitmq.com/中利用rabbitmq模拟器进行消息的模拟发送和接收
一、什么是AMQP,AMQP与rabbitmq的关系
AMQP(Advanced Message Queue Protocol 高级消息队列协议):是一个网络协议,它支持符合条件的客户端和消息代理中间件(message middleware broker)进行通讯。
rabbitmq是AMQP协议的实现者,所以amqp中的概念和准则也适用于rabbitmq。
二、AMQP基本组成及基本概念
1.组成
AMQP的基本组成如下图所示,该模型同样适用于rabbitmq。
基于下图消息的流向:生产者(publisher/producer)生产具有指定路由键(routing key)的消息将其发布给消息代理(broker 即rabbitmq)中的交换机(exchange),交换机将消息中的路由键与队列(queue)绑定信息(binding)中存储的路由键对比,将消息路由到匹配的队列中。队列再将信息通过连接(connection)中的通道(channel)推送给订阅了消息的消费者(consumer)。
2.基本概念
a.生产者(Publisher/Producer):生产者顾名思义就是生产消息的角色。生产者会将消息发送给交换机。为了使交换机正确的将消息路由给队列,发布消息时需指定消息的路由键(routing key)。
b.消息代理(Broker):代理的职能就是接收发布者发布的消息并将消息推送给订阅了消息的消费者。rabbitmq就相当于一个代理。
c.虚拟主机(Virtual Host):出于多租户和安全因素设计的,把AMQP的基本组(交换机,队列,绑定称为AMQP组件)件划分到一个虚拟的分组中,类似于网络中的namespace概念。当多个不同的用户使用同一个borker(RabbitMQ server)提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等。
d.交换机(Exchange):交换机负责接收消息并按照一定的规则将消息路由给队列。路由的规则存储在交换机与队列绑定时指定的routing key。
e.绑定(Binding):交换机和队列之间通过路由键(routing key)相互绑定起来,并根据路由键将消息路由到对应队列。
f.队列(Queue):消息的载体,exchange中的消息将被路由到队列中,并推送给消费者或者被消费者取走。
g.连接(Connection):消费者和生产者与消息代理之间的连接
h.通道(Channel):如果消费者每一次从代理中取消息都建立一次连接的话,在消息量大的情况下建立多个连接将会有巨大的开销。Channel是在Connection内部建立的逻辑连接。如果应用程序支持多线程,可以为每个线程建立单独的通道进行通讯。AMQP method包含了channel id帮助客户端和message broker识别channel,所以channel之间是完全隔离的。Channel作为轻量级的Connection极大减少了操作系统建立TCP connection的开销。
i.消费者(Consumer):接收消息的角色就是消费者
三、交换机
1.交换机的分类
交换机主要分为四种,还有一种比较特殊的默认交换机:
a.直连交换机(direct exchange):将交换机和一个队列绑定起来,并给该绑定一个路由键。当携带路由键的消息发送给交换机时,交换机会寻找具有匹配的路由键的绑定,并将消息路由给对应的队列。该种交换机为直连交换 机。直连交换机经常用来循环分发任务给多个消费者,此时消息的负载均衡是发生在消费者之间的。
对于下图而言:当携带有orange路由键的消息被发送到交换机时,消息会被路由到队列Q1。
b.主题交换机(topic exchange):将交换机和队列绑定起来,并给绑定赋予一个模式路由键。当携带路由键的消息发送给交换机时,交换机会寻找具有匹配的模式路由键的绑定,并将消息路由给对应的队列。该种交换机为主题交换机。主题交换机经常用来实现各种分发、订阅模式及其变种。主题交换机通常用来实现消息的多播路由(multicast routing)。
模式路由键routing key一般使用 . 来分隔单词,而且有两个通配符可以使用。* 代表任意一个单词,#代表0个或多个单词。例如:apple.orange.penaunt,*.orange.*,orange.#。
主题交换机拥有非常广泛的用户案例。无论何时,当一个问题涉及到那些想要有针对性的选择需要接收消息的 多消费者/多应用(multiple consumers/applications) 的时候,主题交换机都可以被列入考虑范围。
使用案例:
-
- 分发有关于特定地理位置的数据,例如销售点
- 由多个工作者(workers)完成的后台任务,每个工作者负责处理某些特定的任务
- 股票价格更新(以及其他类型的金融数据更新)
- 涉及到分类或者标签的新闻更新(例如,针对特定的运动项目或者队伍)
- 云端的不同种类服务的协调
- 分布式架构/基于系统的软件封装,其中每个构建者仅能处理一个特定的架构或者系统。
对于下图而言:当携带routing key为apple.orange.penanut的消息被发送给交换机时,将会被路由到队列Q1中。当lazy.apple.pen被发送到交换机时,将会被路由到队列Q2中。
c.扇形交换机/广播交换机(fanout exchange):将交换机和任意多个队列绑定起来,不管绑定上的路由键,当消息被发送到交换机上时,消息将会被拷贝并路由到所有绑定到该交换机上的队列中。
对下图而言:携带任何routing key的消息被发送到交换机上时,消息都将被拷贝并分发到Q1,Q2,Q3中。
扇形交换机的使用的案例:
-
- 大规模多用户在线(MMO)游戏可以使用它来处理排行榜更新等全局事件
- 体育新闻网站可以用它来近乎实时地将比分更新分发给移动客户端
- 分发系统使用它来广播各种状态和配置更新
- 在群聊的时候,它被用来分发消息给参与群聊的用户。(AMQP没有内置presence的概念,因此XMPP可能会是个更好的选择)
d.头交换机(header exchange):有时消息的路由操作会涉及到多个属性,此时使用消息头就比用路由键更容易表达,头交换机(headers exchange)就是为此而生的。头交换机使用多个消息属性来代替路由键建立路由规则。通过判断消息头的值能否与指定的绑定相匹配来确立路由规则。
我们可以绑定一个队列到头交换机上,并给他们之间的绑定使用多个用于匹配的头(header)。消息代理得从应用开发者那儿取到更多一段信息,换句话说,它需要考虑某条 消息(message)是需要部分匹配还是全部匹配。上边说的“更多一段消息”就是"x-match"参数。当"x-match"设置为“any”时,消息头的任意一个值被匹配就可以满足条件,而当"x-match"设置为“all”的时候,就需要消息头的所有值都匹配成功。
头交换机可以视为直连交换机的另一种表现形式。头交换机能够像直连交换机一样工作,不同之处在于头交换机的路由规则是建立在头属性值之上,而不是路由键。路由键必须是一个字符串,而头属性值则没有这个约束,它们甚至可以是整数或者哈希值(字典)等。头交换机用的比较少,了解一下概念即可。
当携带有{"orange":"apple"}header参数的消息被发送到交换机时,消息将被路由到Q1队列中。
e.默认交换机(default exchange):默认交换机是一种特殊的直连交换机(direct exchange)。它是由消息代理默认声明的,该交换机有一个特性,所有新建的队列都会默认绑定到默认交换机上,并且绑定的routing ke就是队列的名字。
2.交换机的属性
除交换机类型外,在声明交换机时还可以附带许多其他的属性,其中最重要的几个分别是:
-
- Name:交换机名称。
- Durable:消息代理重启后,交换机是否还存在。交换机有两个状态,持久(durable)、暂存(transient)。持久化的交换机会在消息代理重启后依旧存在,而暂存的交换机则不会。
- Auto-delete :当所有与之绑定的消息队列都完成了对此交换机的使用后,删掉它。
- Arguments:依赖代理本身。
四、队列
1.队列属性
除了队列名称,队列也有另外一些属性
-
- Name:队列名,队列名称可以自己声明,也可以由代理来生成。但是自己声明时,不能声明以amp.开头的队列名,因为这是代理内部使用的队列名称格式,如果这样声明,将会抛出异常。
- Durable:和交换机一样,消息代理重启后,队列是否还存在
- Exclusive:只被一个连接使用,连接关闭后,将立即删除队列。
- Auto-delete:当所有的消费者都退订队列后将自动删除该队列
五、消费者
1.消息确认
消费者在处理消息的时候偶尔会失败或者有时会直接崩溃掉。而且网络原因也有可能引起各种稳日。所以AMQP在什么时候删除消息才是正确的呢?AMQP规范给了两种建议:
-
- 当消息代理将消息发送给应用后立即删除,即自动确认机制。
- 待应用发送一个确认回执(acknowledement)后再删除消息,即显示确认模式。
如果一个消费者在尚未发送确认回执的情况下挂掉了,那么AMQP代理会将消息重新投递给另一个消费者。如果当时没有可用的消费者了,消息代理会死等下一个注册到此队列的消费者,然后再次尝试投递。
2.拒绝消息
当一个消费者在收到消息后,由于某种原因导致消息处理失败,消费者可以告诉消息代理拒绝消息,并指明如何处理这条消息——销毁它或者重新放入队列中。
3.预取消息
在多个消费者共享一个队列的时候,可能会出现有的消费者处理很多消息,而有的消费者没有消息可处理。此时可以指定在收到下一个确认回执前,消费者一次可以接受的最大消息数。
六、消息属性和有效载荷
AMQP模型中的消息对象是带有属性的。有些属性及其常见,AMQP中也明确定义了它们,并且开发者们无需费心思思考这些属性名字所代表的具体含义。例如:
- Content type(内容类型)
- Content encoding(内容编码)
- Routing key(路由键)
- Delivery mode (persistent or not)
投递模式(持久化 或 非持久化) - Message priority(消息优先权)
- Message publishing timestamp(消息发布的时间戳)
- Expiration period(消息有效期)
- Publisher application id(发布应用的ID)
有些属性是被AMQP代理所使用的,但是大多数是开放给接收它们的应用解释器用的。有些属性是可选的也被称作消息头(headers。他们跟HTTP协议的X-Headers很相似。消息属性需要在消息被发布的时候定义。
消息能够以持久化的方式发布,AMQP代理会将此消息存储在磁盘上。如果服务器重启,系统会确认收到的持久化消息未丢失。简单地将消息发送给一个持久化的交换机或者路由给一个持久化的队列,并不会使得此消息具有持久化性质:它完全取决与消息本身的持久模式(persistence mode)。将消息以持久化方式发布时,会对性能造成一定的影响(就像数据库操作一样,健壮性的存在必定造成一些性能牺牲)。
参考资料:
https://blog.csdn.net/mx472756841/article/details/50815895
https://blog.csdn.net/whoamiyang/article/details/54954780
https://www.cnblogs.com/frankyou/p/5283539.html
头交换机用的比较少,了解一下概念即可。