RabbitMQ基本术语
相关概念;
生产者(Producer):投递消息。消息:消息体(payload)+标签(label);生产者把消息交给rabbitmq,rabbitmq会根据标签把消息发给感兴趣的消费者。
- 消息体:带业务逻辑的数据
- 标签:表述这条消息,一个交换器的名称或者一个路由键。
消费者(Consumer):接收消息。连接rabbitmq服务器,订阅到队列上。消费消息体。消息路由过程中,消息的标签会丢弃,消息体存入队列
服务节点(Broker):一个broker可以看作一个rabbitmq服务节点或者rabbitmq服务实例。
队列(Queue):rabbitmq内部对象,用于存储消息。消息只能存在队列中。多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊给多个消费者处理(轮询),而不是每个消费者都收到所有的消息并处理。
交换器(Exchange):生产者将消息发送到Exchange,由交换器将消息路由到一个或多个队列中,如果路由不到,或许会返回给生产者,或许直接丢弃。
路由键(RoutingKey):生产者将消息发给交换器的时候,一般会指定一个RoutingKey,用来指定这个消息的路由规则,这个routingkey需要与交换机类型和绑定键联合使用才能最终生效。
绑定(Binding):交换器和队列通过绑定关联起来,在绑定的时候一般会指定一个绑定键,这样就知道如何正确的将消息路由到队列了
生产者将消息发送给交换器时,需要RoutingKey,当BindingKey和RoutingKey相匹配时,消息会被路由到对应的队列中。绑定多个队列到同一个交换器的时候,这些绑定允许使用相同的BindingKey。
例如
- 交换器相当于投递包裹的邮箱
- RoutingKey相当于填写在包裹上的地址
- BindingKey相当于包裹的目的地
- 当地址和实际想要的投递的地址匹配:正确投递到目的地,最后这个目的地的主人-队列可以保留这个包裹
- 地址不匹配:不能正确投递,可能退回,也可能被丢弃
交换器类型
fanout
会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中
direct
会把消息路由到那些BindingKey和RoutingKey完全匹配的队列中。
topic
将消息路由到BindingKey和RoutingKey想匹配的队列中,但匹配规则有些不同
- RoutingKey为“.”分割的字符串,分隔的每一段独立的字符串成为一个单词
- BindingKey和RoutingKey一样也是“."分隔的字符串
- BindingKey中可以存在了两种特殊字符串”*“和”#“,用于做模糊匹配
headers
根据发送的消息内容中的headers属性进行匹配
RabbitMQ运转流程
生产者发送消息
- 生产者连接到rabbitmq broker,建立一个连接,开启一个信道
- 生产者声明一个交换器,并设置相关属性(交换机类型,是否持久化)
- 生产者声明一个队列并设置相关属性(是否排他,是否持久化等)
- 生产者通过路由键将交换器和队列绑定起来
- 生产者发送消息至rabbitmq broker,包含路由键,交换器等
- 响应的交换器根据接收到的路由键查找相匹配的队列
- 如果找到,则将从生产者发送过来的消息存入相应的队列中
- 如果没有找到,根据生产者配置的属性选择丢弃还是回退给生产者
- 关闭信道
- 关闭连接
消费者消费
- 消费者连接到rabbitmq broker ,建立一个连接,开启一个信道
- 消费者向rabbitmq broker请求消息相应队列中的消息,可能会设置相应的回调函数以及做一些准备工作
- 等待rabbitmq broker回应并投递相应队列中的消息,消费者接收消息
- 消费者确认ack接收到的消息
- rabbitmq从队列中删除相应已经被确认的消息
- 关闭信道
- 关闭连接
RabbitMQ 处理每条AMQP指令都是通过信道完成的,信道是建立在Connection上的虚拟连接,就是生产或者消费者与broker建立的tcp连接。
AMQP协议
RabbitMQ就是AMQP协议的Erlang实现,RabbitMQ是AMQP协议的erlang实现,AMQP的模型架构也是:生产者将消息发送给交换器,交换器和队列绑定,当生产者发送消息时所携带的RoutingKey与绑定时的BindingKey相匹配时,消息被存入相应队列中,消费者可以订阅相应的队列来获取消息。
AMQP协议
- Module Layer:协议最高层,主要定义了一些供客户端调用的命令,客户端可以利用这些命令实现自己的业务逻辑,例如客户端可以使用Queue.Declare命令声明一个队列或者使用Basic.consume订阅消费一个队列中的消息
- Session Layer:位于中间层,主要负责客户端的命令发送给服务器,再将服务端的应答返回给客户端,主要为客户端与服务器之间的通信提供可靠性同步机制和错误处理
- Transport Layer:位于最底层,主要传输二进制数据流,提供帧的处理、信道复用、错误检测和数据表示等。
生产者流转过程
- 客户端与broker建立连接,调用factory.newConnection,broker返回Connection.Start建立连接,
- 涉及命令;Connection.Start/.Start-OK、Connection.Tune/.Tune-Ok、Connection.Open/.open-Ok
- 客户准备开启信道,调用connection.createChannel
- 命令:Channel.Open,Channel.Open-Ok
- 客户端发送消息,调用channel.basicPublish
- 命令:Basic.Publish
消费者流转过程
- 客户端与broker建立连接,调用factory.newConnection,broker返回Connection.Start建立连接,
- 涉及命令;Connection.Start/.Start-OK、Connection.Tune/.Tune-Ok、Connection.Open/.open-Ok
- 客户准备开启信道,调用connection.createChannel
- 命令:Channel.Open,Channel.Open-Ok
- 消费之前调用channel.basicQos(int prefetchCount)方法设置消费者客户端最大能保持的未确认的消息数
- 命令:Basic.Qos/.Qos-Ok
- 真正消费前,消费者客户端需要向broker发送Basic.Consume命令将channel置为接收模式,之后broker回执basic.Consume-Ok告诉准备好了
- 消费者接收到消息并正确消费后,向broker发送确认
- 命令:Basic.Ack
- 消费者停止消费,主动关闭连接
- Chanel.Close/.Close-Ok和Connection.Close/.Close-Ok
参考:《RabbitMQ实战指南》