第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)

  • 是一种轻量级的文本协议,用于在客户端和消息代理之间传递消息。
  • 它定义了 CONNECTSUBSCRIBESENDDISCONNECT 等命令。
  • 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 兼容性更好

相关推荐
Victor3562 小时前
MongoDB(39)如何使用聚合进行过滤?
后端
Victor3562 小时前
MongoDB(38)如何使用聚合进行投影?
后端
AI_56783 小时前
基于智优达平台的Python教学实践:从环境搭建到自动评测
开发语言·前端·人工智能·后端·python
IT_陈寒3 小时前
JavaScript开发者必备的5个高效调试技巧,90%的人都不知道最后一个!
前端·人工智能·后端
会编程的土豆3 小时前
Set 深度解析:去重、唯一性与你的智能抽屉
java·开发语言·后端·数据结构与算法
颜酱3 小时前
二分图核心原理与判定算法
javascript·后端·算法
奋斗小强4 小时前
前端工程化:从 Webpack 到 Vite,打包速度提升 10 倍的秘密
后端
我叫黑大帅4 小时前
Golang中实时推送的功臣 - WebSocket
后端·面试·go
朱雨鹏4 小时前
图解RocketMQ运行原理
后端·rocketmq