Spring Boot 整合 RabbitMQ

一、概述:RabbitMQ 是什么?

你可以把 RabbitMQ 想象成一个「快递中转站」。
比如你在网上买了一本书,卖家(生产者)把包裹(消息)交给快递站(RabbitMQ),快递站根据包裹上的地址(规则)把包裹分给不同的快递员(消费者),最后送到你家(业务系统)。

RabbitMQ 是一个专门用来「传递消息」的软件(专业叫「消息中间件」),它能让不同的程序、不同的电脑之间高效地「传小纸条」。


二、RabbitMQ 的「快递分类方式」(交换机类型)

快递站分包裹时,可能按「地址」「重量」「紧急程度」分类。RabbitMQ 也有类似的「分类规则」,叫 交换机(Exchange)。常用的有 4 种:

1. 直连交换机(Direct Exchange)

规则:包裹上必须写「精确地址」(路由键 Routing Key),只有地址完全匹配的快递员才能收到。
例子:卖家给「北京-朝阳区」的包裹,只有负责朝阳区的快递员能接。

2. 扇形交换机(Fanout Exchange)

规则:不管地址,「所有快递员」都能收到包裹(广播模式)。
例子:卖家发「双11大促通知」,所有快递员都要知道,一起准备加班。

3. 主题交换机(Topic Exchange)

规则:地址可以用「通配符」(比如 * 代表一个词,# 代表多个词)。
例子:卖家发「北京.*」的包裹,所有地址以「北京」开头的快递员(如北京-朝阳、北京-海淀)都能收到。

4. 头交换机(Headers Exchange)

规则:不看地址,看包裹上的「标签」(Headers 头信息,比如「优先级=高」)。
例子:卖家标「紧急」的包裹,只有关注「紧急」标签的快递员能接。


三、RabbitMQ 的使用场景(为什么需要它?)

1. 异步处理:省时间!

比如你在淘宝下单,系统需要「扣库存+发短信+更新积分」。如果一步步做,可能要等 5 秒;用 RabbitMQ 可以把「发短信」和「更新积分」的任务丢给 RabbitMQ,主流程只需要 1 秒完成下单,剩下的由其他程序慢慢处理。

2. 流量削峰:防崩溃!

双11时,订单像洪水一样涌来,系统直接处理可能被冲垮。RabbitMQ 像「水库」,把订单暂时存起来,系统按自己的速度慢慢处理(比如每秒处理 1000 单),避免被瞬间的高流量冲垮。

3. 系统解耦:不互相拖累!

比如电商系统有「订单模块」「库存模块」「短信模块」。如果订单模块直接调用库存和短信模块,一旦短信模块崩溃,订单也会失败。用 RabbitMQ 后,订单模块只需要把消息发给 RabbitMQ,其他模块自己来取,互不影响。

四、整合Springboot

1. 配置 RabbitMQ 连接

1.Maven

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

2.配置文件,yml和properties选择一个

spring:rabbitmq:host: 117.185.165.187port: 5672username: rabbitmqpassword: j8iG3KYs7Wmxxx
# RabbitMQ 服务器地址(默认 localhost:5672)
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
# 登录账号密码(默认 guest/guest,注意:远程连接需要改密码!)
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

2、定义「快递规则」:交换机和队列

RabbitMQ 的消息需要通过「交换机(Exchange)」和「队列(Queue)」传递。我们需要先告诉 Spring Boot 要创建哪些交换机和队列。

新建 RabbitMQConfig.java,用 @Bean 声明交换机、队列和绑定关系。

做一个「电商下单后发通知」的功能,需要:

  • 一个直连交换机(order_exchange)。
  • 一个队列(sms_queue),专门存「需要发短信的订单」。
  • 把队列和交换机绑定,路由键是 send_sms(只有路由键匹配的消息才会进这个队列)。
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitMQConfig {// 1. 声明直连交换机(名字叫 order_exchange)@Beanpublic DirectExchange orderExchange() {return new DirectExchange("order_exchange");}// 2. 声明队列(名字叫 sms_queue,存需要发短信的订单)@Beanpublic Queue smsQueue() {return new Queue("sms_queue");}// 3. 把队列和交换机绑定,路由键是 send_sms(只有路由键匹配的消息才会进这个队列)@Beanpublic Binding smsBinding(Queue smsQueue, DirectExchange orderExchange) {return BindingBuilder.bind(smsQueue).to(orderExchange).with("send_sms");  // 路由键必须和生产者发送时一致}
}

如果说是多个队列按照下面的

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitMQConfig {// 1. 声明直连交换机(名字叫 order_exchange)@Beanpublic DirectExchange orderExchange() {return new DirectExchange("order_exchange");}// 2. 声明 3 个队列(短信、积分、日志)@Beanpublic Queue smsQueue() {return new Queue("sms_queue");  // 存需要发短信的订单}@Beanpublic Queue scoreQueue() {return new Queue("score_queue");  // 存需要更新积分的订单}@Beanpublic Queue logQueue() {return new Queue("log_queue");  // 存需要记录日志的订单}// 3. 绑定 sms_queue(路由键 send_sms)@Beanpublic Binding smsBinding(Queue smsQueue, DirectExchange orderExchange) {return BindingBuilder.bind(smsQueue).to(orderExchange).with("send_sms");  // 路由键:只有 send_sms 的消息会进 sms_queue}// 4. 绑定 score_queue(路由键 update_score)@Beanpublic Binding scoreBinding(Queue scoreQueue, DirectExchange orderExchange) {return BindingBuilder.bind(scoreQueue).to(orderExchange).with("update_score");  // 路由键:只有 update_score 的消息会进 score_queue}// 5. 绑定 logQueue(路由键 log_order)@Beanpublic Binding logBinding(Queue logQueue, DirectExchange orderExchange) {return BindingBuilder.bind(logQueue).to(orderExchange).with("log_order");  // 路由键:只有 log_order 的消息会进 log_queue}}

3、生产者:发送消息(卖家发包裹)

RabbitTemplate(Spring 提供的发消息工具)发送消息到交换机。

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class OrderService {// 注入 RabbitTemplate(Spring 自动帮我们创建好的发消息工具)@Autowiredprivate RabbitTemplate rabbitTemplate;// 用户下单后,发送消息到 RabbitMQpublic void createOrder(String orderInfo) {// 1. 主流程:扣库存、保存订单(这里简化,直接打印)System.out.println("主流程:订单已保存,开始扣库存...");// 2. 异步任务:发送短信通知(把消息发给 RabbitMQ)rabbitTemplate.convertAndSend("order_exchange",  // 交换机名字"send_sms",        // 路由键(和队列绑定的路由键一致)orderInfo          // 消息内容(比如订单详情));System.out.println("已发送短信通知任务到 RabbitMQ");}
}

4、消费者:接收消息(快递员收包裹)

@RabbitListener 注解监听队列,自动接收并处理消息。

新建消费者服务类

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
public class SmsConsumer {// 监听 sms_queue 队列,有消息就自动触发这个方法@RabbitListener(queues = "sms_queue")public void sendSms(String orderInfo) {System.out.println("收到短信任务,正在发送...");// 这里调用短信接口(比如阿里云短信),实际代码需要替换System.out.println("已给用户发送短信:" + orderInfo);}
}

如果说是多线程处理就多添加一个配置concurrency = "5"

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
public class SmsConsumer {// 监听 sms_queue 队列,有消息就自动触发这个方法@RabbitListener(queues = "sms_queue",concurrency = "5")public void sendSms(String orderInfo) {System.out.println("收到短信任务,正在发送...");// 这里调用短信接口(比如阿里云短信),实际代码需要替换System.out.println("已给用户发送短信:" + orderInfo);}
}
1、如何避免消息被重复处理?

如果你的场景是「多个消费者抢着处理同一条消息」(比如并行加速),需要确保 一条消息只被一个消费者处理。RabbitMQ 默认已经帮你实现了这一点!

2、原理:消息确认机制(ACK)
  • 当消费者收到消息后,RabbitMQ 会等待消费者「确认」(ACK)。
  • 如果消费者正常处理完消息并返回 ACK,RabbitMQ 会删除这条消息,不会再发给其他消费者。
  • 如果消费者处理失败(比如崩溃),RabbitMQ 会重新将消息分发给其他消费者。
3、注意事项
1. 消息幂等性(防重复处理)

如果消费者处理消息时,因为网络问题导致 ACK 未成功返回,RabbitMQ 会重新发送消息,可能导致重复处理。
解决方法

  • 消息里加唯一标识(如订单号)。
  • 处理前检查是否已处理过(比如查数据库)。
2. 消费者数量别太多!

concurrency 不是越大越好!如果消费者数量超过服务器 CPU 核心数,反而会因为线程切换浪费资源。
建议:根据业务耗时调整,比如处理耗时 1 秒的任务,消费者数量 = CPU 核心数 × 2 比较合理。

3. 手动确认消息(高级场景)

默认是自动 ACK(auto_ack=true),但如果处理消息可能失败(比如调用外部接口超时),建议用手动 ACK。

@RabbitListener(queues = "order_queue", ackMode = "MANUAL")  // 手动确认
public void processOrder(String orderInfo, Channel channel, Message message) {try {// 处理消息...channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);  // 手动确认成功} catch (Exception e) {// 处理失败,重新入队(或发送到死信队列)channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);}
}

五、常见问题 & 注意事项

1. 消息丢失怎么办?

  • 开启「消息持久化」:在声明队列和交换机时,设置 durable=true(默认是 true,重启 RabbitMQ 后消息不丢失)。
  • 生产者确认:配置 spring.rabbitmq.publisher-confirm-type=correlated,确保消息成功发到交换机。
  • 消费者确认:默认是 auto_ack=true(自动确认),如果需要手动确认(比如处理消息时可能失败),可以设置 @RabbitListener(ackMode = "MANUAL"),处理完再调用 channel.basicAck()

2. 重复消费怎么办?

  • 消息里加唯一标识(如订单号),消费者处理前检查是否已处理过(比如查数据库)。

3. RabbitMQ 连不上?

  • 检查 application.properties 里的 hostportusernamepassword 是否正确。
  • 远程连接时,RabbitMQ 默认禁止 guest 用户,需要新建用户并授权(管理界面操作)。

六、总结

用 Spring Boot 整合 RabbitMQ 超简单!核心步骤就 4 步:

  1. 配连接:在 application.properties 里填 RabbitMQ 地址。
  2. 定义规则:用 @Bean 声明交换机、队列和绑定关系。
  3. 发消息:用 RabbitTemplate.convertAndSend() 发送。
  4. 收消息:用 @RabbitListener 监听队列。

适合用 Spring Boot + RabbitMQ 的场景

  • 电商、物流等需要「异步任务」的系统。
  • 高并发场景(如双11订单洪峰)。
  • 多个模块需要「松耦合」协作的系统(如订单、短信、积分模块)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88268.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88268.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/88268.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity Demo-3DFarm详解-其一

我们来拆解一个种田游戏&#xff0c;这个游戏种类内部的功能还是比较模板化的&#xff0c;我们来一点点说。我们大体上分为这么几个部分&#xff1a;农场运营玩法角色与玩家互动物品与背包存档和进度管理用户界面系统农场运营可以大体上分为&#xff1a;种植系统&#xff1a;支…

esp8266驱动下载

问题描述&#xff1a;esp8266插上电脑&#xff0c;设备管理器无法识别&#xff0c;显示为USB serial&#xff08;黄色感叹号&#xff09; 首先确认你的esp8266是不是 CH340 系列的 USB 转串口芯片 CH340驱动下载地址

大语言模型的极限:知识、推理与创造力的边界探析

大语言模型的极限&#xff1a;知识、推理与创造力的边界探析 人工智能领域的快速发展推动了大语言模型&#xff08;LLM&#xff09;的广泛应用&#xff0c;这些模型在文本生成、知识问答和创意表达等方面展现出前所未有的能力。然而&#xff0c;随着应用场景的深化&#xff0c;…

git中的fork指令解释

在Git中&#xff0c;Fork 是指将他人的代码仓库&#xff08;Repository&#xff09;复制到自己的账户下&#xff0c;创建一个完全独立的副本[1][2]。以下是关于Fork的详细说明&#xff1a; Fork的定义与核心作用 定义&#xff1a;Fork是代码托管平台&#xff08;如GitHub&#…

iPhone 抓包工具有哪些?多工具对比分析优缺点

iOS 平台一向以安全性著称&#xff0c;这也使得对其进行网络调试和抓包变得异常困难。相比安卓&#xff0c;iPhone 抓包难点主要在以下几点&#xff1a; 系统限制代理设置的灵活性无法自由安装根证书抓包常涉及 HTTPS 解密与双向认证破解普通用户设备无 root 或越狱权限 因此&a…

使用 libcu++ 库

文章目录使用 libcu 库安装与设置基本组件1. 原子操作2. 内存管理3. 类型特性4. 同步原语编译选项注意事项使用 libcu 库 libcu 是 NVIDIA 提供的 CUDA C 标准库实现&#xff0c;它为 CUDA 开发者提供了类似 C 标准库的功能和接口。以下是使用 libcu 的基本指南&#xff1a; …

[Leetcode] 预处理 | 多叉树bfs | 格雷编码 | static_cast | 矩阵对角线

魔术排列模拟一个特定的洗牌过程&#xff0c;并找到使得经过一系列洗牌和取牌操作后&#xff0c;能够与给定的目标数组target相匹配的最小k值核心思想: 预处理初始排列&#xff1a;从一个按顺序排列的数组&#xff08;例如&#xff0c;{1, 2, 3, ..., n}&#xff09;开始。洗牌…

【技术追踪】SynPo:基于高质量负提示提升无训练少样本医学图像分割性能(MICCAI-2025)

SAM 新用法&#xff0c;无需训练&#xff0c;利用高质量负提示提升分割性能~ 论文&#xff1a;SynPo: Boosting Training-Free Few-Shot Medical Segmentation via High-Quality Negative Prompts 代码&#xff1a;https://liu-yufei.github.io/synpo-project-page/ 0、摘要 大…

深入理解机器学习

一.前言本章节开始来讲解一下机器学习的知识&#xff0c;本期作为一个了解就大概介绍一下&#xff0c;我们不会从机器学习基础开始介绍&#xff0c;但是后面会来补充&#xff0c;随着ai的不断发展&#xff0c;机器学习在ai的领域里面的占比越来约少&#xff0c;我们还是以应用为…

数据结构 顺序表(1)

目录 1.线性表 2.顺序表 1.线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用 的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构&#…

openssl 生成国密证书

openssl生成证书生成CA私钥 openssl ecparam -genkey -name SM2 -out ca.key.pem -noout证书请求 openssl req -new -key ca.key.pem -out ca.cert.req -subj “/CNrtems-strongswan-CA”生成证书 openssl x509 -req -days 3650 -in ca.cert.req -signkey ca.key.pem -out ca.c…

系统架构设计师论文分享-论分布式事务技术及其应用

我的软考历程 摘要 2023年9月&#xff0c;我所在的公司通过了研发纱线MES系统的立项&#xff0c;该系统为国内纱线工厂提供SAAS服务&#xff0c;旨在提高纱线工厂的数字化和智能化水平。我在该项目中担任系统架构设计师一职&#xff0c;负责该项目的架构设计工作。本文结合我…

东土科技智能塔机系统亮相南京,助力智能建造高质量发展

近日&#xff0c;由南京市城乡建设委员会、江苏省土木建筑学会主办的“无人驾驶智能塔机观摩会”&#xff0c;在中建三局一公司南京扬子江智慧中心项目现场成功举办。作为全国首批智能建造试点城市&#xff0c;南京市已出台20余项支持政策&#xff0c;落地93个试点项目&#xf…

3D Surface Reconstruction with Enhanced High-Frequency Details

3D Surface Reconstruction with Enhanced High-Frequency Details核心问题&#xff1a;当前基于神经隐式表示&#xff08;如 NeuS&#xff09;的 3D 表面重建方法&#xff0c;通常采用随机采样策略。这种随机采样难以充分捕捉图像中的高频细节区域&#xff08;如纹理、边缘、光…

Science Robotics 耶鲁大学开源视触觉新范式,看出机器人柔性手的力感知

摘要&#xff1a;在机器人视触觉传感领域&#xff0c;如何兼顾成本与性能始终是一大挑战。耶鲁大学在《Science Robotics》上发表最新研究&#xff0c;提出了一种“Forces for Free”&#xff08;F3&#xff09;新范式。该研究通过观测一个经过特殊优化的开源柔性手&#xff08…

关于java项目中maven的理解

我的理解&#xff1a;maven是java项目的依赖管理工具&#xff0c;通过pom.xml文件配置要下载的依赖&#xff0c;settings.xml配置maven下载的镜像没有就默认在maven中央仓库下载依赖&#xff0c;本地仓库是存储下载好的依赖ai:1. 功能定位局限Maven 不只是依赖管理工具&#xf…

缓存三大问题详解与工业级解决方案

文章目录缓存三大问题详解与工业级解决方案概念总览问题详解1. 缓存穿透 (Cache Penetration)问题描述典型场景危害2. 缓存击穿 (Cache Breakdown)问题描述典型场景危害3. 缓存雪崩 (Cache Avalanche)问题描述典型场景危害工业级解决方案缓存穿透解决方案方案1: 布隆过滤器方案…

FreeRTOS 中主函数 while 循环与任务创建的紧密联系

FreeRTOS 中主函数 while 循环与任务创建的紧密联系 在嵌入式开发领域&#xff0c;FreeRTOS 是一款被广泛应用的轻量级实时操作系统&#xff0c;为开发者提供了高效的多任务调度机制。对于初学者来说&#xff0c;理解主函数中的 while 循环与通过 xTaskCreate 创建的任务之间的…

Flutter基础(前端教程⑦-Http和卡片)

1. 假设后端返回的数据格式{"code": 200,"data": [{"name": "张三","age": 25,"email": "zhangsanexample.com","avatar": "https://picsum.photos/200/200?random1","statu…

pytorch chunk 切块

目录 chunk切块 chunk​​​​​​​切块 import torch# 创建一个形状为 [2, 3, 4] 的张量 x torch.arange(6).reshape(2, 3) print("原始张量形状:", x.shape) print("x:", x) # 输出: 原始张量形状: torch.Size([2, 3, 4])# 沿着最后一个维度分割成 2 …