扫描二维码

关注或者微信搜一搜:编程智域 前端至全栈交流与成长

发现1000+提升效率与开发的AI工具和实用程序https://tools.cmdragon.cn/


1. STOMP协议基础

STOMP(Simple Text Oriented Messaging Protocol)是一种基于文本的轻量级消息协议,常用于实现发布/订阅模式。与直接使用WebSocket相比,STOMP提供了更结构化的消息格式,支持以下核心功能:

  • 消息目的地(Destination):消息发送的目标地址(如"/topic/news")
  • 消息头(Headers):包含元数据的键值对(如消息类型、内容长度)
  • 消息体(Body):实际传输的数据内容(JSON/文本格式)

在FastAPI中实现STOMP协议的核心思路是通过WebSocket建立连接后,在消息处理层添加STOMP协议解析器。整个过程分为三个阶段:

  1. 客户端发送CONNECT帧建立STOMP会话
  2. 使用SUBSCRIBE命令订阅消息通道
  3. 通过SEND命令向指定目的地发送消息
graph TD
A[客户端] -->|WebSocket连接| B(FastAPI服务端)
B --> C{STOMP协议升级}
C -->|成功| D[消息路由器]
C -->|失败| E[关闭连接]
D --> F[订阅管理]
D --> G[消息转发]

2. FastAPI实现STOMP协议

以下示例代码演示了如何在FastAPI中实现STOMP协议支持:

# 环境依赖:fastapi==0.103.0 uvicorn==0.23.2 stomp.py==8.0.1
from fastapi import FastAPI, WebSocket
from stomp import parse_frame, Frame app = FastAPI() class StompManager:
def __init__(self):
self.subscriptions = {} async def handle_connect(self, frame, websocket):
# 协议版本验证
if frame.headers.get('accept-version') != '1.2':
await websocket.send_text('ERROR\nversion-not-supported\n\n')
return False
return True async def handle_subscribe(self, frame, websocket):
destination = frame.headers['destination']
sub_id = frame.headers['id']
self.subscriptions[sub_id] = {
'destination': destination,
'websocket': websocket
} @app.websocket("/stomp")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
manager = StompManager() try:
while True:
data = await websocket.receive_text()
frame = parse_frame(data) if frame.command == 'CONNECT':
if await manager.handle_connect(frame, websocket):
await websocket.send_text("CONNECTED\nversion:1.2\n\n")
elif frame.command == 'SUBSCRIBE':
await manager.handle_subscribe(frame, websocket)
elif frame.command == 'SEND':
# 消息路由逻辑
pass except Exception as e:
print(f"连接异常: {str(e)}")

代码解析:

  1. STOMP帧解析:使用stomp.py库的parse_frame方法解析原始消息
  2. 会话管理:通过StompManager类维护订阅关系
  3. 协议协商:在CONNECT阶段验证协议版本兼容性
  4. 订阅管理:使用字典存储订阅ID与WebSocket的映射关系

3. 最佳实践示例

实现消息广播功能的核心代码:

from typing import Dict
from fastapi import WebSocket
from pydantic import BaseModel class Subscription(BaseModel):
destination: str
websocket: WebSocket class MessageRouter:
def __init__(self):
self.channels: Dict[str, list] = {} async def add_subscriber(self, channel: str, websocket: WebSocket):
if channel not in self.channels:
self.channels[channel] = []
self.channels[channel].append(websocket) async def broadcast(self, channel: str, message: str):
for ws in self.channels.get(channel, []):
await ws.send_text(message) # 在SEND命令处理中调用
async def handle_send(frame, router: MessageRouter):
destination = frame.headers['destination']
await router.broadcast(destination, frame.body)

4. 课后Quiz

问题1:当客户端发送的STOMP协议版本不匹配时,服务端应该返回什么响应?

答案:服务端应返回ERROR帧,并在headers中包含version-not-supported错误码,立即关闭连接。

问题2:如何防止消息路由时的循环广播?

答案:在消息头中添加message-id字段,服务端维护已处理消息ID的缓存,对重复ID的消息直接丢弃。


5. 常见报错处理

报错1STOMP Protocol Error: Missing required header 'destination'

原因:SEND或SUBSCRIBE帧缺少destination头

解决方案

  1. 检查客户端代码是否正确设置destination
  2. 服务端添加头校验逻辑:
if 'destination' not in frame.headers:
await websocket.send_text('ERROR\nmissing-destination\n\n')

报错2WebSocket connection is already closed

原因:尝试向已关闭的连接发送消息

解决方案

# 发送前检查连接状态
for ws in list(self.channels[channel]):
if ws.client_state == WebSocketState.DISCONNECTED:
self.channels[channel].remove(ws)

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

,阅读完整的文章:如何在FastAPI中玩转STOMP协议升级,让你的消息传递更高效?

往期文章归档:

免费好用的热门在线工具

如何在FastAPI中玩转STOMP协议升级,让你的消息传递更高效?的更多相关文章

  1. 如何在.Net中使用Redis

    Redis是一个key-value存储系统.和Memcached类似,但是解决了断电后数据完全丢失的情况,而且她支持更多无化的value类型,除了和string外,还支持lists(链表).sets( ...

  2. 如何在MyBatis中优雅的使用枚举

    问题 在编码过程中,经常会遇到用某个数值来表示某种状态.类型或者阶段的情况,比如有这样一个枚举:   public enum ComputerState { OPEN(10), //开启 CLOSE( ...

  3. 如何在 Kubernetes 集群中玩转 Fluid + JuiceFS

    作者简介: 吕冬冬,云知声超算平台架构师, 负责大规模分布式机器学习平台架构设计与功能研发,负责深度学习算法应用的优化与 AI 模型加速.研究领域包括高性能计算.分布式文件存储.分布式缓存等. 朱唯唯 ...

  4. 如何在 Istio 中支持 Dubbo、Thrift、Redis 以及任何七层协议?

    赵化冰,腾讯云高级工程师,Istio Member,ServiceMesher管理委员,Istio 项目贡献者, Aerika 项目创建者 ,热衷于开源.网络和云计算.目前主要从事服务网格的开源和研发 ...

  5. springboot websocket集群(stomp协议)连接时候传递参数

    最近在公司项目中接到个需求.就是后台跟前端浏览器要保持长连接,后台主动往前台推数据. 网上查了下,websocket stomp协议处理这个很简单.尤其是跟springboot 集成. 但是由于开始是 ...

  6. 我是如何在SQLServer中处理每天四亿三千万记录的

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  7. 【转】我是如何在SQLServer中处理每天四亿三千万记录的

    原文转自:http://blog.jobbole.com/80395/ 首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文 ...

  8. 如何在SQLServer中处理每天四亿三千万记录

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  9. (转)我是如何在SQLServer中处理每天四亿三千万记录的

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  10. 笔记整理--玩转robots协议

    玩转robots协议 -- 其他 -- IT技术博客大学习 -- 共学习 共进步! - Google Chrome (2013/7/14 20:24:07) 玩转robots协议 2013年2月8日北 ...

随机推荐

  1. MySQL 中长事务可能会导致哪些问题?

    MySQL 中长事务可能会导致哪些问题? 长事务是指那些执行时间较长.涉及多个操作且没有及时提交或回滚的事务.长事务在 MySQL 中可能引发一系列问题,尤其是在高并发的数据库环境中.以下是长事务可能 ...

  2. 强化学习框架:OpenRLHF源码解读,模型处理

    强化学习框架:OpenRLHF源码解读,模型处理 本文主要介绍 强化学习框架:OpenRLHF源码解读,模型处理 models框架设计 了解一下 OpenRLHF的模型框架设计范式: From:htt ...

  3. ubuntu nginx + php7.2 + mysql5.7环境搭建

    一.换源 备份原来的源 sudo cp /etc/apt/sources.list /etc/apt/sources_init.list 更换源 sudo gedit /etc/apt/sources ...

  4. xamarin.forms+prism 实现DialogService(对话框服务)

    Getting Started with IDialogAware Creating dialogs with the DialogService requires a ViewModel that ...

  5. SVN之“解决SVN清理失败问题”

    解决SVN清理失败,显示乱码问题 更新SVN时,提示要清理,但是清理失败,此时什么也操作不了,以下就是解决方案. 情况如图: 解决方案一: 下载splite3 新建一个临时文件夹,使用英文名字,将解压 ...

  6. django笔记补充

    安装 pip install django环境变量: C:\Program Files\Anaconda3\Scriptsdjango-admin startproject mysite 创建djan ...

  7. SQL 强化练习 (九)

    这两天在写一个权限的sql, 涉及 3 张表, 然后做了一个 union all 的操作, 感觉效率有点问题, 写套娃, 改来改去的做优化. 关键数据又不能贴, 嗯, 还是明天搞个假数据来说明这个关系 ...

  8. Python实验4 列表与字典应用

    目的 :熟练操作组合数据类型. 试验任务: 基础:生日悖论分析.如果一个房间有23 人或以上,那么至少有两 个人的生日相同的概率大于50%.编写程序,输出在不同随机样本数 量下,23 个人中至少两个人 ...

  9. CentOS Stream 10安装部署Zabbix 7.0网络监控平台和设备配置添加

    以下是在CentOS Stream 10上部署Zabbix 7.0监控平台,并配置多种监控目标的完整操作指南: 一.Zabbix 7.0 基础环境部署 1. 系统准备 # 更新系统 sudo dnf ...

  10. SpringSecurity配置 2

    SpringSecurity配置 2 目前的现状,虽然是有了登录认证的接口,但是登录完成后,当我们访问受保护的接口时,即使将 Token 令牌携带与请求一起发送,依然是无法请求成功.另外,提示信息如下 ...