RabbitMQ基本概念介绍

   目录

一、Producer:生产者,消息的投递方

二、Consumer :消费者,就是接收消息的一方

三、Broker :消息中间件的服务节点

四、Queue :队列,是RabbitMQ的内部对象,用于存储消息

五、Exchange:交换器

1.fanout

2.direct

3.topic

4.headers

六、RoutingKey :路由键

七、Binding :绑定


        RabbitMQ整体上是一个生产者与消费者模型,主要负责接收、存储和转发消息。可以把消息传递的过程想象成:当你将一个包裹送到邮局,邮局会暂存并最终将邮件通过邮递员送到收件人的手上,RabbitMQ就好比由邮局、邮箱和邮递员组成的一个系统。从计算机术语层面来说,RabbitMQ模型更像是一种交换机模型。

      

一、Producer:生产者,消息的投递方

     生产者创建消息,然后发布到RabbitMQ中。消息一般可以包含2个部分:消息体和标签label)。消息体也可以称之为payload,在实际应用中,消息体一般是一个带有业务逻辑结构的数据,比如一个JSON字符串。当然可以进一步对这个消息体进行序列化操作。消息的标签来表述这条消息,比如一个交换器的名称和一个路由键。生产者把消息交由RabbitMQ,RabbitMQ之后会根据标签把消息发送给感兴趣的消费者(Consumer)。


二、Consumer :消费者,就是接收消息的一方

      消费者连接到RabbitMQ服务器,并订阅到队列上。当消费者消费一条消息时,只是消费消息的消息体(payload)。在消息路由的过程中,消息的标签会丢弃,存入到队列中的消息只有消息体,消费者也只会消费到消息体,也就不知道消息的生产者是谁,当然消费者也不需要知道。


三、Broker :消息中间件的服务节点

        对于RabbitMQ来说,一个RabbitMQBroker可以简单地看作一个RabbitMQ服务节点,或者RabbitMQ服务实例。大多数情况下也可以将一个RabbitMQBroker看作一台RabbitMQ服务器。


四、Queue :队列,是RabbitMQ的内部对象,用于存储消息

      RabbitMQ消息都只能存储在队列中,这一点和Kafka这种消息中间件相反。Kafka将消息存储在topic(主题)这个逻辑层面,而相对应的队列逻辑只是topic实际存储文件中的位移标识。RabbitMQ的生产者生产消息并最终投递到队列中,消费者可以从队列中获取消息并消费。

       多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin即轮询)多个消费者进行处理,而不是每个消费者都收到所有的消息并处理

      RabbitMQ不支持队列层面的广播消费,如果需要广播消费,需要在其上进行二次开发,处理逻辑会变得异常复杂,同时也不建议这么做。


五、Exchange:交换器

          生产者将消息发送到Exchange(交换器,通常也可以用大写的"X"来表示),由交换器将消息路由到一个或者多个队列中。如果路由不到,或许会返回给生产者,或许直接丢弃。这里可以将RabbitMQ中的交换器看作一个简单的实体。

RabbitMQ常用的交换器类型有fanout、direct、topic、headers这四种。AMQP协议里还提到另外两种类型:System和自定义,这里不予描述。

1.fanout

         它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中,不用管routeKey的事。

2.direct

   direct类型的交换器路由规则也很简单,它会把消息路由到那些 BindingKey 和RoutingKey(可以先看下面内容)完全匹配的队列中, 例子:        

//发布消息的是RoutingKey,这里是warning
channel.basicPublish(EXCHANGE_NAME,"warning",MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());

           

         如果在发送消息的时候设置路由键为"info"或者"debug",消息只会路由到Queue2。如果以其他的路由键发送消息,则消息不会路由到这两个队列中。

3.topic

      前面讲到direct类型的交换器路由规则是完全匹配BindingKey 和RoutingKey,但是这种严格的匹配方式在很多情况下不能满足实际业务的需求。ω p i c类型的交换器在匹配规则上进行了扩展,它与direct类型的交换器相似,也是将消息路由到BindingKey和RoutingKey相匹配的队列中,但这里的匹配规则有些不同,它约定:

  • RoutingKey为一个点号"."分隔的字符串(被点号"."分隔开的每一段独立的字符串称为一个单词) ,如“com.wusu.vison”、“com.rabbit.client”;
  • BindingKey 和RoutingKey一样也是点号"."分隔的字符串;
  • BindingKey 中可以存在两种特殊字符串"*"和"#",用于做模糊匹配,其中"*"用于匹配一个单词,“#”用于匹配多个单词(包含零个)

例如:

  • 路由键为"com.rabbitmq.client "的消息会同时路由到Q u e u e l和Q u e u e 2 ;
  • 路由键为"com.hidden.client "的消息只会路由到Q u e u e 2中:·
  • 路由键为"com.hidden.demo "的消息只会路由到Q u e u e 2中:·
  • 路由键为" java.rabbitmq.demo "的消息只会路由到Q u e u e l中:·
  • 路由键为"java.util.concurrent "的消息将会被丢弃或者返回给生产者(需要设置mandatory参数),因为它没有匹配任何路由键。

 

4.headers

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


六、RoutingKey :路由键

          生产者将消息发给交换器的时候,一般会指定一个RoutingKey,用来指定这个消息的路由规则,而这个RoutingKey需要与交换器类型和绑定键( BindingKey )联合使用才能最终生效。在交换器类型和绑定键( BindingKey  )固定的情况下,生产者可以在发送消息给交换器时,通过指定RoutingKey来决定消息流向哪里。


七、Binding :绑定

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

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

 

比较RoutingKey和BindingKey :

从代码角度上来看:

         Channel channel = connection.createChannel();//创建信道
        //创建一个type="direct" 、持久化,非自动删除的交换器
        channel.exchangeDeclare(EXCHANGE_NAME,"direct",true,false,null);
        //创建一个持久化,非排他的,非自动删除的队列
        channel.queueDeclare(QUEUE_NAME,true,false,false,null);  
        //将交换器与队列通过路由绑定,绑定的ROUTING_KEY就是BindingKey,只是这里和RoutingKey相同
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY); 
        //发送持久化信息
        String message = "hello world";
         //这是生产这发布消息,使用RoutingKey发布消息用来路由信息   
    channel.basicPublish(EXCHANGE_NAME,ROUTING_KEY,MessageProperties.PERSISTENT_TEXT_PLAIN,
message.getBytes());

          以上代码声明了一个direct类型的交换器,然后将交换器和队列绑定起来。注意这里使用的字样是"ROUTING_KEY",在本该使用BindingKey的channel. queueBind方法中却和channel.basicPublish方法同样使用了RoutingKey,这样做的潜台词是:这里的RoutingKey和BindingKey是同一个东西。在d i r e c t交换器类型下,RoutingKey和BindingKey需要完全匹配才能使用,所以上面代码中采用了此种写法会显得方便许多。但是在t o p i c交换类型下,RoutingKey和BindingKey之间需要做模糊匹配,两者并不是相同的。BindingKey其实也属于路由键中的一种,官方解释为:the routing key  to  use  for  the  b i n d i n g。可以翻译为:在绑定的时候使用的路由键。大多数时候,包括官方文档和R a b b i t M Q Java API,中都把BindingKey和RoutingKey看作RoutingKey。

这篇文章基本算是参考《RabbitMQ In Action》书籍的学习笔记。

阅读更多

没有更多推荐了,返回首页