介绍
什么是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=admin3、配置队列
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();}}