【RabbitMQ】RabbitMQ与AMQP协议简介(五)
一、AMQP与rabbitmq的关系
AMQP(高级消息队列协议)是一个网络协议。它支持符合要求的客户端应用(application)和消息中间件代理(messaging middleware broker)之间进行通信。
而RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现。
二、AMQP messaging 中的基本概念
Connection
- 对应底层一个AMQP-Client到RabbitMQ-Broker的一个TCP连接。
- 这边要考虑两个端点问题,在TCP连接建立完成后,如下图所示,连接的目标Broker就已经确定是集群中的一台了,由于是长连接,除非断连重建,否则对端节点不可变。
- 所以从这里可以看出RabbitMQ相比Pulsar、RocketMQ不一样的地方在于,其是一种服务端寻址模型,以Client的视角来看,想要连接任意Exchange、Queue,只要连上任意一台Broker就行。
Channel
- 信道,可以理解为一种逻辑连接,体现了多路复用的设计思路。
- 支持串行执行,包括收和发的指令,可以理解为一种半双工模式的“虚拟网络通道”。
- 所有Exchange、Queue、Binding的操作都是在Channel之上进行的。
Vhost
- 等价于一种租户隔离概念,不同Vhost下可以创建同名Exchange、Queue,这样可以进行业务隔离。
- RabbitMQ的权限隔离和权限控制的机制是在Vhost级别的。
- Rabbit官方原生的全局Policy控制在Vhost级别。
Exchange
- 一个虚拟实体,声明不同消息的路由策略,自身不存储消息。
- 一个路由器,基于消息头部的RoutingKey和Header将消息路由到符合条件的具体的Queue。
- 支持单播和广播。
Queue
- 消息存储实体,是消息底层存储的容器,类似Pulsar的Topic。
- 单订阅模式,其下的Consumer分别消费到一部分消息。
- 和存储关联,因此有容量上限、ttl等存储层的特性。
- 支持多消费和独占消费,取决于你订阅时设置的参数。由于它是存储消息系统的消息,所以内部基于一个消费位点控制持久化消费进度,记录最后被消费并Ack的位置。
- 面向Consumer。
Binding
- 衔接Exchange和Queue的桥梁,本质是一个规则的声明。
- 一个Exchange下可以有多个Binding。
- 一个Queue也可以被多个Binding关联。
- 一个Exchange到一个Queue也可以声明多个Binding。
Broker
- 可以看做RabbitMQ的服务节点。一般请下一个Broker可以看做一个RabbitMQ服务器
三、AMQP协议本身包括三层:
- Module Layer:位于协议的最高层,主要定义了一些供客户端调用的命令,客户端可以利用这些命令实现自己的业务逻辑。例如:客户端可以使用Queue.Declare命令声明一个队列或者使用Basic.Consum订阅消费一个队列中的消息。
- Session Layer:位于中间层,主要负责将客户端的命令发送给服务器,再将服务器的应答返回给客户端,主要为客户端与服务器之间的通信提供可靠性同步机制和错误处理。
- Transport Layer:位于最底层,主要传输二进制数据流,提供帧的处理、信道复用、错误检测和数据表示等。
AMQP说到底还是一个通信协议,通信协议都会涉及报文交互,从low-level层面举例来说,AMQP本身是应用层的协议,其填充于TCP协议层的数据部分,而从high-level层面来说,AMQP是通过协议命令交互的。AMQP协议可以看作是一系列结构化命令的集合,这里的命令代表一种操作,类似于Http中的方法(GET、POST、PUT、DELETE等)
AMQP生产者流转过程
当客户端与Broker(RabbitMQ服务器)建立连接的时候,会调用factory.newConnection方法,这个方法会进一步封装成Protocol Header的报文头发送给Broker,以此来通知Broker本次交互采用的是AMQP协议,紧接着Broker返回Connection.Start来建立连接,在连接的过程中涉及Connection.Start/.Start-OK、Connection.Tune/.Tune-OK、Connection.Open/.Open-ok这6个命令的交互。
当客户端调用connection.createChannel方法准备开启信道的时候,其包装Channel.Open命令发送给Broker,等待Channel.Open-Ok命令。
当客户端发送消息的时候,需要调用channel.basicPublish方法,对应的AMQP命令为Basic.Publish,注意这个命令和前面涉及的命令略有不同,这个命令还包括了Content Header和Content Body。Content Header里面包含的是消息体的属性,例如:投递模式、优先级等,而Content Body包含消息体的本身。
当客户端发送完消息需要关闭资源时,涉及Channel.Close/.Close-Ok与Connection.Close/.Close-Ok的命令交互。详细的流转过程如下图
AMQP消费者流转过程
消费者客户端同样需要与Broker建立连接,与生产者客户端一样,协议交互同样涉及Connection.Start/.Start-Ok、Connection.Tune/.Tune-Ok和Connection.Open/.Open-Ok等。
紧接着就是在Connection之上建立channel,和之前的生产者一样协议涉及Channel.Open/Open-Ok。
如果在消费之前调用了Channel.basicQos(int prefetchCount)的方法来设置消费者客户端最大能“保持”的未确认的消息数(即预取个数),那么协议流转就会涉及Basix.Qos/.Qos-Ok这两个AMQP命令。
在真正的消费之前,消费者客户端需要向Broker发送Basic.Consume命令(即调用channel.basicConsume方法)将Channel设置为接收模式,之后Broker回执Basic.Consume-Ok以告诉消费者客户端准备好消费消息。紧接着Broker向消费者客户端推送消息(Push),即Basic.Deliver命令,有意思的是这个和Basic.Publish命令一样会携带Content Header 和Content Body。
消费者接收到消息并正确消费后,向Broker发送确认,即Basic.Ack命令。
在消费者停止消费的时候,主动关闭连接,这点和生产者是一样的,涉及到Channel.Close/Channel-Ok和Connection.Close/.Close-Ok。
参考:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?