简介
RabbitMQ是一个流行的消息中间件,它基于AMQP协议,提供了一个可靠的消息队列服务。
- 生产者(Producer):消息的发送方,负责将消息发送到RabbitMQ。
- 消费者(Consumer):消息的接收方,从RabbitMQ接收消息并进行处理。
- 消息(Message):在RabbitMQ中传输的数据,它由消息头和消息体组成。
- 队列(Queue):消息的存储地,生产者发送的消息会被放入队列中,消费者从队列中获取消息。
- 交换器(Exchange):接收来自生产者的消息,并将消息根据路由规则发送到一个或多个队列。RabbitMQ支持多种类型的交换器,例如:
- 直接交换器(Direct Exchange):根据路由键将消息路由到具有匹配路由键的队列。
- 主题交换器(Topic Exchange):根据路由键和模式匹配将消息路由到队列。
- 扇出交换器(Fanout Exchange):将消息发送到所有绑定的队列,不考虑路由键。
- 头交换器(Headers Exchange):根据消息的头属性进行路由。
- 绑定(Binding):交换器和队列之间的虚拟连接,它定义了消息如何从交换器路由到队列。
- 虚拟主机(Vhost):RabbitMQ服务器的命名空间,拥有自己的队列、交换器和绑定,可以看作是消息的隔离环境。
- 连接(Connection):客户端与RabbitMQ服务器之间的TCP连接。
- 通道(Channel):在客户端和RabbitMQ之间的虚拟连接,大多数RabbitMQ操作都在通道上进行,如声明队列、发送和接收消息等。
- 持久性(Durability):消息或队列的持久性设置,确保消息或队列在RabbitMQ服务器重启后依然存在。
- 确认(Acknowledgement):消费者接收并处理消息后,向RabbitMQ发送的确认信号,表示消息已被成功处理。
- 死信队列(Dead Letter Exchange):当消息无法被正常处理时,会被发送到死信队列。
SpringBoot接入RabbitMQ

点对点(单队列方式)

该方式只需要我们定义一个队列,然后向队列中发送消息即可,然后消费者监听该队列。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
队列设置
@Configuration
public class SampleConfig {
public static final String QUEUE = "SAMPLE_QUEUE";
@Autowired
private AmqpAdmin amqpAdmin;
@Bean(QUEUE)
public Queue sampleQueue(){
return new Queue(QUEUE);
}
public static final String QUEUE2 = "SAMPLE_QUEUE2";
@Bean(QUEUE2)
public Queue sampleQueue2(){
return new Queue(QUEUE2);
}
}
生产者
@Component
public class SampleProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String message){
rabbitTemplate.convertAndSend(SampleConfig.QUEUE, message);
rabbitTemplate.convertAndSend(SampleConfig.QUEUE2, message);
}
}
消费者
消费者,我们也可以定义多个消费者,监听同一个队列,这样就进行了负载均衡,消息会按照顺序消费,生产过程中一般也是这样使用的(只不过是利用的线程池来消费)。
@Slf4j
@Component
public class SampleConsumer {
@RabbitListener(queues = SampleConfig.QUEUE)
public void fire(String message){
log.info("收到消息" + message);
}
@RabbitListener(queues = SampleConfig.QUEUE)
public void fire1(String message){
log.info("收到消息1" + message);
}
}
测试
@RestController
@RequestMapping(value = "test")
public class TestController {
@Autowired
private SampleProducer sampleProducer;
@GetMapping(value = "sampleProducer")
public Object sampleProducer(){
sampleProducer.send("sampleProducer" + System.currentTimeMillis());
return "SUCCESS";
}
}
发布订阅模式(fanout)
该模式就像是订阅新闻一样,我喜欢这个新闻,我订阅它,当它更新的时候就会给你推送最新的新闻;该模式需要引入交换机概念。

Exchange交换机和Queue队列配置
@Configuration
public class FanoutConfig {
public static final String QUEUE_ZS = "collect_zs";
public static final String QUEUE_LS = "collect_ls";
public static final String EXCHANGE_COLLECT = "exchange_collect";
@Bean
public FanoutExchange fanoutExchangeCollect(){
return new FanoutExchange(EXCHANGE_COLLECT);
}
@Bean
public Queue queueCollectZs(){
return new Queue(QUEUE_ZS);
}
@Bean
public Queue queueCollectLs(){
return new Queue(QUEUE_LS);
}
@Bean
public Binding bindingZs(FanoutExchange fanoutExchangeCollect, Queue queueCollectZs){
return BindingBuilder.bind(queueCollectZs).to(fanoutExchangeCollect);
}
@Bean
public Binding bindingLs(FanoutExchange fanoutExchangeCollect, Queue queueCollectLs){
return BindingBuilder.bind(queueCollectLs).to(fanoutExchangeCollect);
}
}
生产者
@Service
public class FanoutProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String message){
rabbitTemplate.convertAndSend(FanoutConfig.EXCHANGE_COLLECT, "", message);
}
}
消费者
@Slf4j
@Service
public class FanoutConsumer {
@RabbitListener(queues = FanoutConfig.QUEUE_ZS)
public void fireZs(String message){
log.info("张三收到消息" + message);
}
@RabbitListener(queues = FanoutConfig.QUEUE_LS)
public void fireLs(String message){
log.info("李四收到消息" + message);
}
}
测试
@RestController
@RequestMapping(value = "test")
public class TestController {
@Autowired
private FanoutProducer fanoutProducer;
@GetMapping(value = "fanoutProducer")
public Object fanoutProducer(String message){
fanoutProducer.send("fanoutProducer:" + message + System.currentTimeMillis());
return "SUCCESS";
}
}
结果
2024-07-11 09:25:19.192 INFO 1572 --- [ntContainer#0-1] c.h.rabbitmq.demo.fanout.FanoutConsumer : 张三收到消息fanoutProducer:你好1720661119173
2024-07-11 09:25:19.193 INFO 1572 --- [ntContainer#1-1] c.h.rabbitmq.demo.fanout.FanoutConsumer : 李四收到消息fanoutProducer:你好1720661119173
2024-07-11 09:25:24.485 INFO 1572 --- [ntContainer#0-1] c.h.rabbitmq.demo.fanout.FanoutConsumer : 张三收到消息fanoutProducer:你好a1720661124482
2024-07-11 09:25:24.492 INFO 1572 --- [ntContainer#1-1] c.h.rabbitmq.demo.fanout.FanoutConsumer : 李四收到消息fanoutProducer:你好a1720661124482
路由选择模式(direct)
该模式下我们只需要关注我们关心的消息,比如系统发送的日志,普通的日志收集器则需要关注error、info、warning,但是报警服务则只需要关注error级别的日志,下面给出使用案例。

Exchange交换机和Queue队列、Routing路由配置
@Configuration
public class DirectConfig {
public static final String QUEUE_LOG_ALL = "queue_log_all";
public static final String QUEUE_LOG_ERROR = "queue_log_error";
public static final String EXCHANGE_LOG = "log";
public static final String ROUTING_KEY_INFO = "info";
public static final String ROUTING_KEY_ERROR = "error";
@Bean
public DirectExchange directExchangeLog(){
return new DirectExchange(EXCHANGE_LOG);
}
@Bean
public Queue queueLogAll(){
return new Queue(QUEUE_LOG_ALL);
}
@Bean
public Queue queueLogError(){
return new Queue(QUEUE_LOG_ERROR);
}
@Bean
public Binding bindingInfoToAll(Queue queueLogAll, DirectExchange directExchangeLog){
return BindingBuilder.bind(queueLogAll).to(directExchangeLog).with(ROUTING_KEY_INFO);
}
@Bean
public Binding bindingErrorToAll(Queue queueLogAll, DirectExchange directExchangeLog){
return BindingBuilder.bind(queueLogAll).to(directExchangeLog).with(ROUTING_KEY_ERROR);
}
@Bean
public Binding bindingErrorToError(Queue queueLogError, DirectExchange directExchangeLog){
return BindingBuilder.bind(queueLogError).to(directExchangeLog).with(ROUTING_KEY_ERROR);
}
}
生产者
@Service
public class DirectProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String routingKey, String message){
rabbitTemplate.convertAndSend(DirectConfig.EXCHANGE_LOG, routingKey, message);
}
}
消费者
@Slf4j
@Service
public class DirectConsumer {
@RabbitListener(queues = DirectConfig.QUEUE_LOG_ALL)
public void fireAll(String message){
log.info("接收所有日志:" + message);
}
@RabbitListener(queues = DirectConfig.QUEUE_LOG_ERROR)
public void fireError(String message){
log.info("接收ERROR日志:" + message);
}
}
测试
@RestController
@RequestMapping(value = "test")
public class TestController {
@Autowired
private DirectProducer directProducer;
@GetMapping(value = "directProducer")
public Object directProducer(String routingKey, String message){
directProducer.send(routingKey, "directProducer:" + message + System.currentTimeMillis());
return "SUCCESS";
}
}
结果
2024-07-11 10:32:48.856 INFO 20856 --- [ntContainer#1-1] c.h.rabbitmq.demo.direct.DirectConsumer : 接收所有日志:directProducer:info日志1720665168842
2024-07-11 10:32:54.364 INFO 20856 --- [ntContainer#1-1] c.h.rabbitmq.demo.direct.DirectConsumer : 接收所有日志:directProducer:info日志1720665174363
2024-07-11 10:33:05.009 INFO 20856 --- [ntContainer#1-1] c.h.rabbitmq.demo.direct.DirectConsumer : 接收所有日志:directProducer:error日志1720665185007
2024-07-11 10:33:05.010 INFO 20856 --- [ntContainer#0-1] c.h.rabbitmq.demo.direct.DirectConsumer : 接收ERROR日志:directProducer:error日志1720665185007
2024-07-11 10:33:08.103 INFO 20856 --- [ntContainer#0-1] c.h.rabbitmq.demo.direct.DirectConsumer : 接收ERROR日志:directProducer:error日志1720665188102
2024-07-11 10:33:08.103 INFO 20856 --- [ntContainer#1-1] c.h.rabbitmq.demo.direct.DirectConsumer : 接收所有日志:directProducer:error日志1720665188102
通配符模式Topics
该模式其实和Direct模式差不多,只不过路由键可以配置为通配符,这样让我们配置更方便简单。下面随便列了使用方式,匹配dog.*路由键和cat.*的路由键。

配置类
@Configuration
public class TopicsConfig {
public static final String QUEUE_DOG = "dog";
public static final String QUEUE_CAT = "cat";
public static final String EXCHANGE_ANIMAL = "animal";
public static final String ROUTING_KEY_DOG = "dog.*";
public static final String ROUTING_KEY_CAT = "cat.*";
@Bean
public Queue queueDog(){
return new Queue(QUEUE_DOG);
}
@Bean
public Queue queueCat(){
return new Queue(QUEUE_CAT);
}
@Bean
public TopicExchange topicExchangeAnimal(){
return new TopicExchange(EXCHANGE_ANIMAL);
}
@Bean
public Binding bindingDog(Queue queueDog, TopicExchange topicExchangeAnimal){
return BindingBuilder.bind(queueDog).to(topicExchangeAnimal).with(ROUTING_KEY_DOG);
}
@Bean
public Binding bindingCat(Queue queueCat, TopicExchange topicExchangeAnimal){
return BindingBuilder.bind(queueCat).to(topicExchangeAnimal).with(ROUTING_KEY_CAT);
}
}
生产者
@Service
public class TopicsProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String routingKey, String message){
rabbitTemplate.convertAndSend(TopicsConfig.EXCHANGE_ANIMAL, routingKey, message);
}
}
消费者
@Slf4j
@Service
public class TopicsConsumer {
@RabbitListener(queues = TopicsConfig.QUEUE_DOG)
public void fireDog(String message){
log.info("狗收到消息" + message);
}
@RabbitListener(queues = TopicsConfig.QUEUE_CAT)
public void fireCat(String message){
log.info("猫收到消息" + message);
}
}
测试
@RestController
@RequestMapping(value = "test")
public class TestController {
@Autowired
private TopicsProducer topicsProducer;
@GetMapping(value = "topicsProducer")
public Object topicsProducer(String routingKey, String message){
topicsProducer.send(routingKey, "topicsProducer:" + message + System.currentTimeMillis());
return "SUCCESS";
}
}
结果
2024-07-11 12:47:42.586 INFO 21200 --- [ntContainer#6-1] c.h.rabbitmq.demo.topics.TopicsConsumer : 狗收到消息topicsProducer:红色的狗1720673262558
2024-07-11 12:47:55.628 INFO 21200 --- [ntContainer#6-1] c.h.rabbitmq.demo.topics.TopicsConsumer : 狗收到消息topicsProducer:蓝色的狗1720673275621
2024-07-11 12:48:04.502 INFO 21200 --- [ntContainer#7-1] c.h.rabbitmq.demo.topics.TopicsConsumer : 猫收到消息topicsProducer:蓝色的猫1720673284499
进阶
过期时间TTL
死信队列
延迟队列
消息确认机制
消息追踪
常问问题
消息堆积
消息丢失
有序消费消息
重复消费
配置
RabbitMq单机
RabbitMq集群
控制台
RabbitMQ的概览情况,里面包括集群各个节点的信息、端口映射信息。

1. Overview(概览)
1.1 Totals(总数)

1.1.1 Queued messages
当前Vhost下的所有队列消息情况
| 参数 | 简述 |
|---|
| Ready | 准备好的消息数量(生产者生产的消息已经到达Broker,可以让消费者消费的数量)。 |
| Unacked | 全称Unacknowledged,待应答的消息总数。 |
| Total | Ready和Unacked的数量总和。 |
1.1.2. Message rates
消息速率
| 参数 | 简述 |
|---|
| Publish | 生产者生产消息的速率 |
| Publisher confirm | broker确认生产消息的速率 |
| Deliver(manual ack) | customer手动确认的速率 |
| Deliver( auto ack) | customer自动确认的速率 |
| Consumer ack | customer正在确认的速率 |
| Redelivered | 正在传递’redelivered’标志集的消息的速率 |
| Get (manual ack) | 响应basic.get而要求确认的消息的传输速率 |
| Get (auto ack) | 响应basic.get而发送不需要确认的消息的速率 |
| Get (empty) | 从队列中获取消息,但队列当前没有可用的消息可供获取。 |
| Return | 将basic.return发送给producter的速率 |
| Disk read | queue从磁盘读取消息的速率 |
| Disk write | queue从磁盘写入消息的速率 |
1.1.3. Global counts
各个组件的总数【统计当前选择的Vhost下的】。
| 参数 | 简述 |
|---|
| Connections | client的tcp连接的总数 |
| Channels | 通道的总数 |
| Exchange | 交换器的总数 |
| Queues | 队列的总数 |
| Consumers | 消费者的总数 |
1.2. Nodes(节点消息)
启动一个 broker 都会产生一个 node 。
broker的属性
| 参数 | 简述 |
|---|
| Name | broker名称 |
| File descriptors | broker打开的文件描述符实际数量和限制值。 |
| Socket descriptors | broker管理的网络套接字数量和限制。当限制被耗尽时,RabbitMQ将停止接受新的网络连接。实际使用值一般略大于Connections |
| Erlang processes | erlang启动的进程实际数量和限制值。 |
| Memory | 当前broker占用的内存实际值和限制值 |
| Disk space | 当前broker占用的磁盘实际值和限制值。 |
| Uptime | 当前broker持续运行的时长。 |
| Info | 当前broker基本配置信息。 |
| Reset stats | 重启节点或者集群。 |
1.3. Churn statistics(生产统计)

1.4. Port and contexts(相关使用端口描述)

1.5. Export definitions(导出配置)

1.6. Import definitions(导入配置)

2. Connections(连接)

2.1 Overview(概览)
| 参数 | 简述 |
|---|
| Virtual host | Vhost名称。 |
| Name | 客户端连接的IP和端口。 |
| User name | 连接使用的用户名。 |
| State | 当前的状态。running:运行中;idle:空闲。 |
2.2 Detail(详情)
| 参数 | 简述 |
|---|
| SSL/TLS | 是否使用ssl进行连接。 |
| Protocol | 使用的协议。 |
| Channels | 当前连接上的channel总数。 |
| Channel max | 允许的最大channel数量。 |
| Frame max | 与客户端协商的允许最大包大小,若包太大会拆分成多次发送,默认是131072=128K。 |
| Authentication | 当前连接认证方式。 |
2.3 Network(网络)
| 参数 | 简述 |
|---|
| From client | 每秒发出的数据包。 |
| To client | 每秒收到的数据包。 |
| Heartbeat | 连接心跳检测时间,默认60s,设置0表示不做心跳检测。 |
| Connected at | 连接创建时间。 |
3. Channels(通道)

3.1. Overview(概览)
| 参数 | 简述 |
|---|
| Channel | 通道名称。 |
| Virtual host | Vhost 名称。 |
| Mode | 通道保证模式(消息确认方式)C或者T,或者都不是C(confirm):Channel will send streaming publish confirmations.(确认模式)。T(transactional):Channel is transactional.(事务模式)。 |
| State | 通道状态。idle:空闲,runing:运行。 |
3.2. Details(详情)
| 参数 | 简述 |
|---|
| Unconfirmed | 未确认的消息。 |
| prefetch | 通道预取消息数量。 |
3.3. Transactions
| 参数 | 简述 |
|---|
| Uncommitted msgs | 未提交的消息的数量。 |
| Uncommitted acks | 未提交ACK的消息数量。 |
3.4. Message rates
| 参数 | 简述 |
|---|
| publish | 产生消息的速率。 |
| confirm | 确认消息的速率。 |
| deliver/get | 获取消息的速率。 |
| redelivered | 重新投递消息的速率。 |
| ack | 消息应答的速率。 |
4. Exchanges(交换机)

| 参数 | 简述 |
|---|
| Virtual host | Vhost 名称。 |
| Name | 交换机名称。 |
| Type | 交换机类型。direct:直连,fanout:群发,headers:headers的匹配形式,tipic:广播。 |
| Features | 交互机属性。Durability(是否持久化),Auto delete(是否自动删除),Internal(是否是内部使用)。 |
| Message rate in | 消息进入的速率【接手生产者消息】。 |
| Message rate out | 消息出去的速率【将消息发送到对应队列】。 |
5. Queues and Streams(队列和流)

5.1. Overview(概览)
| 参数 | 简述 |
|---|
| Virtual host | Vhost 名称。 |
| Name | 交换机名称。 |
| Type | 队列的类型。 |
classic:是 RabbitMQ 的默认队列类型,也被称为 standard。它适用于大多数情况,支持消息的基本路由和持久性。 | |
quorum:是 RabbitMQ 引入的一个新类型,在提高队列的可靠性。quorum 队列使用一个复制机制,确保消息在多个节点上持久化,从而增强容错能力和数据可靠性。适用于高可靠性和高可用性要求的场景。 | |
stream:是 RabbitMQ 的流队列类型,支持大规模的消息流处理。stream 队列适用于处理大量数据流,支持消息的顺序处理和持久化。 | |
| Features | 队列属性。D:持久化,Lim:消息最大数量限制。 |
| Consumers | 消费者数量。 |
| Consumer utilisation | 消费者使用率。 |
| state | 队列状态。idle:空闲,runing:运行。 |
5.2. Messages(消息)
| 参数 | 简述 |
|---|
| Ready | 准备好可以消费的消息数量。 |
| Unacked | 正在消费但是未返回ACK的消息数量。 |
| In Memory | 在内存中的消息数量 |
| persistent | 持久化的消息数量 |
| Total | 消息总数。Ready+Unacked。 |
5.3. Messages bytes
| 参数 | 简述 |
|---|
| Ready | 准备好可以消费的消息大小。 |
| In Memory | 在内存中的消息大小 |
| persistent | 持久化的消息大小 |
| Total | 消息总大小。Ready+Unacked。 |
5.4. Messages rate
| 参数 | 简述 |
|---|
| incoming | 消息进入的速率。 |
| deliver/get | 获取消息的速率 |
| redelivered | 重新投递消息的速率 |
| ack | 消息应答的速率 |