消息队列和RabbitMQ
消息队列和RabbitMQ
1.简介
RabbitMQ是最常见的消息队列中间件之一,相比Kafka在中小型项目中应用更广。该文针对RabbitMQ在Java环境的使用进行展开。主要是通过RabbitMQ来深入理解消息队列(下简称MQ)这一种中间件。
该中间件是基于Erlang语言开发的,也自带Erlang的Emnesia分布式实时关系数据库
2.控制界面
通过http://localhost:15672/可以访问RabbitMQ的控制中心,需要输入账号密码,默认需要在localhost下使用guest/guest才能登陆。
在控制界面中可以看到消息队列的信息接收情况以及相关统计信息,也可查看消息内部的payload(即消息主体) 也可以查看目前消息队列的连接情况、硬件使用情况等
3.生产者(P)与消费者(C)
在消息队列中,向消息队列发送消息的一方被称为生产者(Producer),顾名思义就是生产消息,生产者可以异步地向MQ中传递消息,仅需要与消息队列进行短期的连接。 而从消息队列中接收消息,并完成相应工作的一方被称为消费者(Consumer),完成工作的行为被称为是消费。消费者需要保持与MQ的连接和监听。
通常情况下P产生的消息是按照顺序进入MQ的,C也按照队列顺序消费消息
如果存在多个消费者同时运行,MQ会默认按照轮询(Round-robin)的方式将消息均匀分给各个消费者,在理想情况下每个消费者接收到的消息数量是基本相同的。设置prefetchCount=1可以要求调度时仅考虑空闲消费者,不会出现频繁等待运行中消费者的情况。
4.消息确认机制
RabbitMQ支持消息确认(message Acknowledge)机制,即消费者通过发送确认消息来告诉MQ消息的处理情况,MQ一旦接收到确认即可删除消息。RabbitMQ提供了手动消息确认和自动消息确认两种模式,通过autoAck关键词来选择模式。
RabbitMQ在默认情况下使用手动消息确认,应当通过basicAck()方法手动地进行确认。若消费者因为连接关闭、连接丢失等原因在消费途中死亡(未发送确认),RabbitMQ会将消息重新排队,将其重新发送给另一个消费者,直到消息被确认或者超时(默认30min)为止。
在自动消息确认的情况下(即autoAck=true),一个消息一旦被传递给C,就会立刻被标记为已删除,这种情况下无论是否被成功消费,该消息都会丢失。
5.交换机与路由

上图是RabbitMQ消息队列的模型,X为交换机,生产者产生的消息会被传递给交换机(exchange),交换机再根据需要将消息分配给相应的消息队列(需要与交换机进行绑定),最后交付给对应的消费者。
为了实现几种角色之间的连接,明确路由关系,通过键来实现路由规则。
**路由键(Routing Key)**是消息的键,用于发送至交换机时指定路由规则
**绑定键(Binding Key)**是队列的键,用于将队列与交换机关联起来,不同队列可以拥有相同的键,一个队列也可以拥有多个不同的键,因此可以实现多绑定
交换机包括五种模式,如下:
- 直连(Direct):将消息推送到
binding key与消息routing key相同的队列,不匹配的消息会被丢失 - 主题(Topic):消息的
routing key必须是由点号分隔的一系列单词(如alpha.beta.gamma),队列的binding key也需要用点号分隔一系列单词和#、*,其中#表示匹配一个或多个任意单词,*表示匹配一个任意单词(类似正则表达式)。若键值为单个#,表示接收所有消息,若键值不包含#或*,工作模式与直连交换机完全相同。 - 扇形(Fanout):广播消息,会将消息传递给所有与该交换机绑定的队列,速度最快。该交换机不使用key
- 首部(Headers):类似HTTP,使用
Headers头部将消息映射队列,用Object类型规则进行匹配。不使用key - 默认(Default):实际上是名字为空字符串的直连交换机,所有新建队列都会自动绑定至默认交换机上,
routing key与队列名称相同
6.发布-订阅模式
一般的消息队列工作模式是一条消息经由一个消费者处理后完成生命周期(一对一)。而发布-订阅模式是向多个消费者发布同一条消息(一对多)。
实现发布订阅模式的方式是通过扇形交换机实现的