简介
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写的消息队列,可以做到服务间高度解耦,异步通信性能高,流量削峰
AMQP
即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。其主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全
消息确认
1.消费者在消费完消息后发送一个回执给RabbitMQ,RabbitMQ收到消息回执(Message acknowledgment)后才将该消息从Queue中移除
2.如果RabbitMQ没有收到回执并检测到消费者的RabbitMQ连接断开,则RabbitMQ会将该消息发送给其他消费者(如果存在多个消费者)进行处理
3.不存在处理超时概念,一个消费者处理消息时间再长也不会导致该消息被发送给其他消费者,除非它的RabbitMQ连接断开
发送方确认
需要将信道channel设置为confirm模式,一旦信道进入confirm模式,所有的信道上发布的消息都会被指派一个唯一的ID。当消息被投递到队列后,服务器会调用生产者回调借口,使得生产者知道消息是否发送成功
事务
对事务的支持是AMQP协议的一个重要特性。假设当生产者将一个持久化消息发送给服务器时,因为发送消息本身没有任何Response返回,所以即使服务器崩溃,没有持久化该消息,生产者也无法获知该消息已经丢失。如果此时使用事务,即通过txSelect()开启一个事务,然后发送消息给服务器,然后通过txCommit()提交该事务,即可以保证,如果txCommit()提交了,则该消息一定会持久化,如果txCommit()还未提交即服务器崩溃,则该消息不会服务器就收。Rabbit MQ也提供了txRollback()命令用于回滚某一个事务
持久化
每个队列和交换器都有durable属性,它决定了RabbitMQ是否需要持久化队列或者交换器,该属性默认是false,将它设置为true就代表了持久性,当然做到这点还不够,还要将消息的“投递模式”(delivery mode)属性设置为2(持久),同时发布到持久化的交换器中并到达持久化的队列中才完成了消息的持久化
预取数
如果有多个消费者同时订阅同一个Queue中的消息,Queue中的消息会被平摊给多个消费者。这时如果每个消息的处理时间不同,有可能会导致某些消费者一直在忙,而另外一些消费者很快就处理完手头工作并一直空闲的情况。可以通过设置prefetchCount来限制Queue每次发送给每个消费者的消息数,比如设置prefetchCount=1,则Queue每次给每个消费者发送一条消息;消费者处理完这条消息后Queue会再给该消费者发送一条消息
交换器(Exchange)
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
exchange:消息交换器,指定按照什么逻辑将消息路由到队列
常用的Exchange Type有fanout、direct、topic、headers四种,Exchange如图X
扇出(fanout):会把所有发送到fanout Exchange的消息都会被转发到与该Exchange 绑定(Binding)的所有Queue上,其实是一种广播行为
匹配(direct):会将消息中的RoutingKey与该Exchange关联的所有Binding中的BindingKey进行比较,如果相等,则发送到该Binding对应的Queue中
主题(topic):会按照正则表达式,对RoutingKey与BindingKey进行匹配,如果匹配成功,则发送到对应的Queue中
headers:Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配,当消息发送到Exchange时,RabbitMQ会取到该消息的headers(是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue
运行模式
单一模式:即单机情况不做集群,就单独运行一个rabbitmq而已。
普通模式:以两个节点(rabbit01、rabbit02)为例来进行说明。对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列的结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01、rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer。所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。当rabbit01节点故障后,rabbit02节点无法取到rabbit01节点中还未消费的消息实体。如果做了消息持久化,那么得等rabbit01节点恢复,然后才可被消费;如果没有持久化的话,就会产生消息丢失的现象。
镜像模式:把需要的队列做成镜像队列,存在与多个节点属于RabbitMQ的HA方案。该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用。