ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

RabbitMQ - 入门教程

RabbitMQ - 入门教程

介绍

什么是MQ

RabbitMQ官网地址:https://www.rabbitmq.com/
官网下载地址:http://www.rabbitmq.com/download.html
中文地址:https://rabbitmq.cn/
中文文档地址:https://rabbitmq.cn/docs

消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已。

其主要用途:不同进程Process/线程Thread之间通信。

为什么需要消息队列

不同进程(process)之间传递消息时,两个进程之间耦合程度过高,改动一个进程,引发必须修改另一个进程,为了隔离这两个进程,在两进程间抽离出一层(一个模块),所有两进程之间传递的消息,都必须通过消息队列来传递,单独修改某一个进程,不会影响另一个;

不同进程(process)之间传递消息时,为了实现标准化,将消息的格式规范化了,并且,某一个进程接受的消息太多,一下子无法处理完,并且也有先后顺序,必须对收到的消息进行排队,因此诞生了事实上的消息队列;

总结
MQ 的出现,核心是把“同步直接调用”改造成“异步消息传递”,从而解决分布式系统的耦合、阻塞、峰值压力、可靠传递和事件广播问题。
它最核心的三个关键词是:解耦、异步、削峰;再往后才是可靠重试、最终一致性、顺序消息、事件驱动等能力。

MQ的五种队列

五种队列

模式核心角色消息分发规则典型场景
简单队列1生产者,1消费者,1队列一条消息只能被一个消费者消费一对一通信,如简单的任务处理
工作队列1生产者,多个消费者,1队列消息被多个消费者竞争消费,默认轮询分发任务分发、负载均衡,如短信通知服务
发布/订阅1生产者,1 Fanout交换机,多个队列/消费者广播:消息复制多份,发送给所有绑定的队列广播通知,如天气预报推送给多个门户网站
路由模式1生产者,1 Direct交换机,多个队列/消费者定向:根据Routing Key精确匹配,发送到指定队列按规则定向传递,如错误日志单独处理
主题模式1生产者,1 Topic交换机,多个队列/消费者通配符匹配:Routing Key支持*和#模糊匹配灵活的多条件路由,如按用户角色、地区过滤消息

简单队列 (Simple Queue)

最基础的一对一模型。生产者将消息直接发送到队列,一个消费者从该队列接收并处理。

  • 特点:配置简单,轻量级。但一个队列只有一个消费者,无法实现负载均衡,消息处理能力有限。
  • 适用:消息量不大、处理逻辑简单的单一消费者场景。

工作队列 (Work Queue)

在简单队列基础上增加消费者,多个消费者监听同一个队列,共同消费消息,实现并行处理。

  • 分发规则:默认采用轮询(Round-Robin)方式,将消息依次分发给每个消费者。也可以配置为“能者多劳”模式,让处理快的消费者获取更多消息。
  • 特点:提高了系统的吞吐量和并行处理能力,但消息的处理顺序无法保证。
  • 适用:任务处理耗时、需要多消费者并行处理的场景,如集群环境下的异步任务分发。

发布/订阅模式 (Publish/Subscribe)

消息不再直接进入队列,而是先发送到Fanout(扇出)交换机。该交换机会将消息广播给所有绑定到它的队列。

  • 特点:一条消息会被多个消费者同时接收,实现广播效果。发布者与订阅者完全解耦。
  • 适用:需要将同一事件通知给多个系统的场景,如实时通知、数据同步。

路由模式 (Routing)

使用Direct(直接)交换机。交换机会根据消息携带的Routing Key,将其精确投递到Binding Key完全匹配的队列中。

  • 特点:实现了有选择的定向分发,只有Routing Key匹配的队列才能收到消息,而非广播给所有队列。
  • 适用:需要根据特定规则(如日志级别、消息类型)将消息路由到不同处理队列的场景。

主题模式 (Topic)

使用Topic(主题)交换机,是路由模式的超集。Routing Key支持通配符匹配。

  • 通配符规则:*匹配一个单词,#匹配零个或多个单词。例如,user.*.order可以匹配user.vip.order,user.#可以匹配user.vip.order.create。
  • 特点:路由规则非常灵活,可以实现复杂的多条件过滤。
  • 适用:需要根据多个维度(如地区、类型、优先级)进行灵活消息分发的复杂业务场景。

SpringBoot集成

springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp对消息各种支持。

1、配置pom文件,主要是添加spring-boot-starter-amqp的支持

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>

2、配置application.properties文件
配置rabbitmq的安装地址、端口以及账户信息

spring.application.name=spirng-boot-rabbitmqspring.rabbitmq.host=127.0.0.1spring.rabbitmq.port=5672spring.rabbitmq.username=adminspring.rabbitmq.password=admin

3、配置队列

packagecom.zpc.rabbitmq;importorg.springframework.amqp.core.Queue;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassRabbitConfig{@BeanpublicQueuequeue(){returnnewQueue("q_hello");}}

4、发送者

packagecom.zpc.rabbitmq;importorg.springframework.amqp.core.AmqpTemplate;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjava.text.SimpleDateFormat;importjava.util.Date;@ComponentpublicclassHelloSender{@AutowiredprivateAmqpTemplaterabbitTemplate;publicvoidsend(){Stringdate=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(newDate());//24小时制Stringcontext="hello "+date;System.out.println("Sender : "+context);//简单对列的情况下routingKey即为Q名this.rabbitTemplate.convertAndSend("q_hello",context);}}

5、接收者

packagecom.zpc.rabbitmq;importorg.springframework.amqp.rabbit.annotation.RabbitHandler;importorg.springframework.amqp.rabbit.annotation.RabbitListener;importorg.springframework.stereotype.Component;@Component@RabbitListener(queues="q_hello")publicclassHelloReceiver{@RabbitHandlerpublicvoidprocess(Stringhello){System.out.println("Receiver : "+hello);}}

6、测试

packagecom.zpc.rabbitmq;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublicclassRabbitMqHelloTest{@AutowiredprivateHelloSenderhelloSender;@Testpublicvoidhello()throwsException{helloSender.send();}}
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进