第2篇:Spring Boot + WebSocket + 消息队列STOMP协议(Rabbitmq) 架构原理

🧩 整体架构概览

复制代码
[Web 浏览器 / 客户端] 
        ↓ (通过 WebSocket 连接)
[Spring Boot 应用] 
        ↓ (通过 TCP 连接 STOMP 协议)
[RabbitMQ(启用了 STOMP 插件)]
  • 客户端:通常是浏览器中的 JavaScript(如 SockJS + Stomp.js),通过 WebSocket 连接到 Spring Boot 应用。
  • Spring Boot 应用:作为"网关"或"桥接器",它不自己处理消息持久化或广播,而是将 STOMP 消息转发给真正的消息中间件(RabbitMQ)。
  • RabbitMQ :作为真正的消息代理(Message Broker),负责消息的存储、路由、广播、持久化、集群等。

🔍 各组件/角色详解

1. STOMP(Simple Text Oriented Messaging Protocol)

  • 是一种轻量级的文本协议,用于在客户端和消息代理之间传递消息。
  • 它定义了 CONNECT、SUBSCRIBE、SEND、DISCONNECT 等命令。
  • WebSocket 本身只是传输通道,而 STOMP 在其上提供语义化的消息格式(类似 HTTP 之于 TCP)。

✅ 所以:WebSocket 是传输层,STOMP 是应用层协议。


2. Spring Boot 内置的 Simple Broker vs. Relay Broker

✅ Simple Broker(内存代理)
  • Spring 自己实现的一个简易消息代理。
  • 只支持 /topic 和 /queue 前缀。
  • 不支持跨实例、无持久化、无集群,仅适合开发测试。
✅ Relay Broker(中继代理)
  • Spring 不处理消息 ,而是将所有 STOMP 消息转发给外部消息中间件(如 RabbitMQ、ActiveMQ)。
  • 外部中间件负责真正的消息路由、持久化、集群、高可用等。
  • 适用于生产环境。

⚠️ 你配置的 .enableStompBrokerRelay(...) 就是启用 Relay 模式。


3. RabbitMQ(作为 STOMP Broker)

默认 RabbitMQ 不支持 STOMP,需要手动启用插件:

复制代码
rabbitmq-plugins enable rabbitmq_stomp

启用后,RabbitMQ 会监听一个 STOMP 端口(默认 61613),接受 STOMP 协议的连接。

注意:RabbitMQ 的 STOMP 插件会自动将 STOMP 的 /topic/xxx 映射为 fanout exchange ,/queue/xxx 映射为 direct queue。


4. 两个登录凭证的作用

复制代码
.setClientLogin("admin").setClientPasscode("admin")     // 客户端 → RabbitMQ
.setSystemLogin("admin").setSystemPasscode("admin")     // Spring Boot → RabbitMQ
角色 谁在用? 用途
Client Login/Passcode Spring Boot 代表前端客户端连接 RabbitMQ 时使用的凭据 当前端订阅 /topic/chat,Spring 会用这个账号在 RabbitMQ 上创建消费者
System Login/Passcode Spring Boot 自身连接 RabbitMQ 时使用的凭据 用于向 RabbitMQ 发送消息(比如 Controller 中调用 convertAndSend("/topic/notice", msg))

💡 实际上,Spring Boot 会维护两条到 RabbitMQ 的 STOMP 连接:

  • 一条用 system 凭据 ,用于发送消息(生产者)
  • 一条用 client 凭据 ,用于代表所有前端用户订阅消息(消费者)

🔄 消息流转示例

假设用户 A 发送一条聊天消息:

  1. 前端 JS 通过 WebSocket + STOMP 向 Spring Boot 发送:

    复制代码
    stompClient.send("/app/chat", {}, JSON.stringify({text: "Hello"}));
  2. Spring Boot 的 @MessageMapping("/chat") 方法收到消息。

  3. 方法内部调用:

    复制代码
    simpMessagingTemplate.convertAndSend("/topic/chatroom", message);
  4. Spring Boot 使用 system 凭据 ,通过 STOMP 协议将消息发给 RabbitMQ 的 /topic/chatroom。

  5. RabbitMQ 将消息广播给所有订阅了 /topic/chatroom 的消费者。

  6. Spring Boot 用 client 凭据 已经代表所有在线用户订阅了该 topic。

  7. RabbitMQ 把消息推给 Spring Boot。

  8. Spring Boot 再通过各自的 WebSocket 连接,把消息推送给每个前端用户。

✅ 所有消息实际都经过 RabbitMQ,Spring Boot 只是"代理转发"。


🛠️ 配置要点总结

项目 说明
setRelayHost("localhost") RabbitMQ 的 IP 或域名
setRelayPort(61613) RabbitMQ STOMP 插件监听的端口(不是 AMQP 的 5672)
用户名/密码 必须在 RabbitMQ 中创建对应用户,并赋予 stomp 权限
目标前缀 /topic, /queue 必须与 RabbitMQ STOMP 插件的默认 destination 映射规则一致

✅ 最佳实践建议

  1. 生产环境务必使用 Relay Broker + RabbitMQ/ActiveMQ,不要用 Simple Broker。
  2. RabbitMQ 需要:
    • 启用 rabbitmq_stomp 插件
    • 创建专用用户(如 stomp-user),并授权 virtual host 和 STOMP 权限
  3. Spring Security 要放行 WebSocket 端点(如 /ws-stomp/**)
  4. 前端使用 SockJS + Stomp.js 兼容性更好

相关推荐
余槐i3 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
需要8263 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
凤山老林4 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
伯恩bourne5 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
张彦峰ZYF5 小时前
停顿短不等于延迟低:G1、ZGC 与低延迟服务的目标分野、代价账本与选型标定
后端·回收暂停、应用停止总时长·到达安全点、分配停滞·屏障吃吞吐、并发线程吃核心·并发窗口吃堆余量·分区式靠挑回收集兑现目标·染色指针式不支持压缩引用
pride.li6 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
upala6 小时前
【仓颉语言入门 · 第二篇 第 6 课】
后端
罗丹丹Luna6 小时前
移动端显示“已提交”以后:SAP 与低代码集成该怎样暴露真实状态
后端·架构
码事漫谈6 小时前
因为太想讨好你,所以AI会骗你
后端
吴凡wudianmei6 小时前
每调一次模型都花钱?如何用工程手段把调用压到最少?
前端·后端·架构