1、RabbitMq 整体模型架构

RabbitMq 消息队列(一)

2、RabbitMq 角色 & 概念

 

2.1 生产者(Producer)

生产者(Producer):
        用于创建消息,是投递消息方。生产者创建消息,然后把消极交给RabbitMq,RabbitMq会根据标签(Label)把消息发送给感兴趣的消费者(Consumer)。其中消息一般包含两部分:消息体(payload)标签(Label)
 
消息体(payload): 一般是一个带有业务逻辑结构的数据,比如一个Json字符串。
 
标签(Label): 用来表述这条消息,比如一个交换器的名称和一个路由键。

2.2 消费者(Consumer)

消费者(Consumer):
        接受消息方,消费者连接RabbitMq服务器,并订阅到队列上。当消费者消费一条消息时,实际上只是消费了消息的消息体(payload)。在消息路由的过程中(Exchange到Queue的过程),消息的标签会丢掉,存入到队列中的消息只有消息体(payload ),消费者只会消费到消息体(payload)。对于消费者而言,不知道也不需要知道消息的生产者是谁。

2.3 消息中间件的服务节点(Broker)

        一个RabbitMq Broker可以简单的理解为一个RabbitMq服务节点,或RabbitMq服务实例,或更加粗暴的理解为一台RabbitMq服务器。RabbitMq Broker作为一个大概念,包含了交换器(Exchange)和队列(Queue)。

2.4 交换器(Exchange)

        交换器有四种类型:fanout、direct、topic、headers。生产者将消息发送到Exchange(交换器,也可用大写“X”表示),由交换器(Exchange)将消息路由到一个或多个队列(Queue)中。如果路由不到,可能会返回给生产者,也可能会直接丢失。

2.5 队列(Queue)

队列(Queue): 属于RabbitMq内部对象,用于存储消息。
        RabbitMq中的消息多只能存储在队列中。生产者生产消息,并将消息最终投递到队列中,消费者从队列中获取消息再消费。多个消费者可以订阅同一个队列,这种情况下队列中的消息会平均分摊(Round-Robin轮询)给多个消费者进行处理,而不是每个消费者都能收到所有的消息并处理。

2.6 路由键(RoutingKey)

        生产者将消息发给交换器时,一般会指定一个RoutingKey,用来指定这个消息的路由规则,而这个RoutingKey需要与交换器类型和绑定键(BindingKey)联合使用才能生效。

2.7 绑定(Binding)

        RabbitMq中通过绑定将交换器与队列关联起来,在绑定的时候一般会指定一个绑定键(BindingKey),这样RabbitMq就知道将消息如何正确的路由到队列了。

        生产者将消息发送给交换器时,需要一个RoutingKey,当BindingKey和RoutingKey相匹配时,消息会被路由到对应的队列中。在绑定多个队列到同一个交换器时,这些绑定允许使用相同的BindingKey。同时BindingKey的生效也依赖于交换器的类型。比如交换器类型为fanout时,会无视BindingKey,而是将消息路由到所有绑定到该交换器的队列中。大多数情况下会将BindingKey写成RoutingKey,特别是交换器类型为direct时。

RabbitMq 消息队列(一)

3、RabbitMq 消息流转

 

3.1 RabbitMq 消息流转图

 
                                               消息流转详细可参考下面流程图:

 
RabbitMq 消息队列(一)
 
        需要说明的是,上图中业务处理部分,业务处理逻辑并不一定需要和接受消息的逻辑使用同一线程。消费者进程可以使用一个线程去接收消息,存入到内存中。业务处理逻辑使用另一个线程从内存读取数据。这样能提高整个应用的处理效率,将应用进一步解耦。

 

3.2 生产者消息流转

 
生产者发送消息:

1、生产者连接到RabbitMq Broker,建立一个连接(Connection),开启一个信道(Channel)。
2、生产者声明一个交换器,并设置相关属性,比如交换机类型、是否持久化等信息。
3、生产者声明一个队列并设置相关属性,比如是否排他、是否支持持久化、是否自动删除等信息。
4、生产者通过路由键将交换器和队列绑定起来。
5、生产者发送消息至RabbitMq Broker,其中包含路由键、交换器等信息。
6、相应的交换器根据接收到的路由键查找相匹配的队列。
7、如果找到,则将从生产者发送过来的消息存入相应的队列中。
8、如果没找到,则根据生产者配置的属性选择丢弃或回退给生产者。
9、关闭信道(Channel)。
10、关闭连接(Connection)。

 

3.3 消费者消息流转

 
消费者接收消息的过程:

1、消费者连接到RabbitMq Broker,建立一个连接(Connection),开启一个信道(Channel)。
2、消费者向RabbitMq Broker请求消费相应队列中的消息,可能会设置相应的回调函数,以及做一些准备工作。
3、等待RabbitMq Broker回应并投递相应队列中的消息,消费者接收消息。
4、消费者确认(ack)接收到的消息。
5、RabbitMq从队列中删除相应已经被确认的消息。
6、关闭信道(Channel)。
7、关闭连接(Connection)。

 

4、交换器(Exchange)类型

 
        RabbitMq 的交换器有四种常用类型:fanoutdirecttopicheaders。同时,AMQP协议中还有另外两种类型:System和自定义。
 

4.1 fanout

        fanout类型会把所有发送到该交换器的消息,路由到所有与该交换器绑定的队列中。

4.2 direct

       direct类型的交换器路由规则很简单,它会把消息路由到那些BindingKey和RoutingKey完全匹配的队列中。

4.3 topic

       topic类型的交换器也是需要匹配 BindingKey 和 RoutingKey,但是比 direct 类型更加灵活,可以说是对direct类型的扩展。
 
        topic 类型约定:

  1. RoutingKey为一个点好“.”分割的字符串。被点号“.”分隔开的每一段独立的字符串,均称为一个单词。例:“com.orgine.api”、“java.util.hidden”等;
  2. BindingKey和RoutingKey一样也是点号“.”分隔的字符串;
  3. BindingKey中可以存在两种特殊的字符“”和“#”,用来做模糊匹配,其中“”用来匹配一个单词,“#”用来匹配多个单词(可以是零个)。

4.4 headers

       headers类型的交换器,不依赖于路由键(RoutingKey)的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。在绑定队列和交换器时制定一组键值对,当发送消息到交换器时,RabbitMq会获取到该消息的headers(也是一个键值对形式),对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对。如果完全匹配,则消息会路由到该队列,否则不会路由到该队列。
       headers类型的交换器性能会很差,并且不实用,所以很少使用该类型。

相关文章: