1、RabbitMQ简介
RabbitMQ是采用erlang语言实现AMQP(Advanced Message Queuing protocol,高级消息队列协议)的消息中间件,它最初起源于金融系统,用于在分布式系统中存储转发消息。
RabbitMQ发展到今天,被越来越多的人认可,这和它在易用性,通用性,可靠性和可扩展性等方面的卓越表现是分不开的。RabbitMQ的具体特点被概括为以下几点:
2、核心概念
消息一般由2部分组成,消息头和消息体,消息体可以成为payload,消息体是不透明的,而消息头则由一些列的可选属性组成,包括routing-key(路由键),priority(相对于其他消息的优先权),delivery-mode(指出该消息可能需要永久性存储等)。生产者把消息交给RabbitMQ后,根据消息头把消息发给感兴趣的消费者。
Exchange(交换器)用来接收生产者的消息并将这些消息路由服务器中的队列去,如果路由不到,或许会返还给生产者,或许被丢弃掉,
交换器的4种类型:不同的类型对应着不同的路由策略,direct,topic,fanout,headers
交换器示意图如下:
生产者将消息发给交换器的时候,一般会指定一个RoutingKey(路由键),用来指定这个消息的路由规则,而这个RoutingKey需要与交换器类型和绑定键联(BindingKey)合使用才能最终生效。
RabbitMQ通过Binding(绑定)与Exchange(交换器)与Queue(消息队列)关联起来,在绑定的时候一般会指定一个BindingKey,这样RabbitMQ就知道如何将消息路由到指定的消息队列了,
Binding示意图:
生产者将消息发送给交换器时,需要一个RoutingKey,当BindingKey和RoutingKey相匹配时,消息就会被路由到相应的队列中。在绑定多个多列到同一交换器的时候,这些绑定允许使用的相同的BindingKey。BindingKey并不是在所有情况下都生效,它依赖于交换器的类型,比如fanout类型的交换器就会无视,而是将消息路由到所有绑定到该交换器的队列中。
用来保存消息直到发送给消费者,它是消息的容器也是消息的终点。一个消息可以投入一个或者多个队列。消息一直在队列里等待消费者连接到这个队列将其取走。
RabbitMQ中的消息只能存在队列中,这一点和kafka这种消息中间件相反。kafka将消息存储在topic这个逻辑层面,而相对应的队列逻辑只是topic实际存储中的位移标识。
多个消费者可以订阅同一个队列,消息会被平均分摊(Round-Robin,轮询)给多个消费者处理,避免消息被重复消费。
RabbitMQ 不支持队列层面的广播消费,如果有广播消费的需求,需要在其上进行二次开发,这样会很麻烦,不建议这样做。
一个RabbitMQ Broker可以简单地看作一个RabbitMQ节点,或者RabbitMQ服务实例。大多数情况下可以将一个RabbitMQ Broker看作一台RabbitMQ服务器。
常用的由direct(默认),fanout,topic,headers四种。
将所有发送到交换器的消息路由到所有与他绑定的队列中,不做任何判断操作,所以速度最快。
把消息路由到那些BandingKey与RoutingKey完全匹配的队列中。
发送消息的时候设置路由键为warning,那么消息会路由到Queue1,Queue2中。
发送消息的时候设置路由键为info,debug,那么消息会路由到Queue2中。
以其他路由键发送消息,则消息不回路由到这2个队列中。
常用来处理有优先级的任务,根据任务的优先级把消息发送到对应的队列,这样可以指派更多的资源去处理优先级更高的队列。
和direct类似,允许模糊匹配。
路由键为 “com.rabbitmq.client” 的消息会同时路由到 Queuel 和 Queue2;
路由键为 “com.hidden.client” 的消息只会路由到 Queue2 中;
路由键为 “com.hidden.demo” 的消息只会路由到 Queue2 中;
路由键为 “java.rabbitmq.demo” 的消息只会路由到Queuel中;
路由键为 “java.util.concurrent” 的消息将会被丢弃或者返回给生产者(需要设置 mandatory 参数),因为它没有匹配任何路由键。
根据发送消息内容中的headers属性进行匹配。在绑定队列和交换器时制定一组键值对,当发送消息到交换器时,RabbitMQ会获取到该消息的headers(键值对)对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果完全匹配则路由到该队列。性能差,不实用。
RabbitMQ安装文档见安装文章。