FastAPI 实战:WebSocket 从入门到上线,使用避坑指南 📅 发布时间:2026/7/16 6:12:40 👁️ 浏览次数: 你是不是觉得 WebSocket 挺简单的不就建立个连接然后 send 和 onmessage 吗我当初也这么想直到我做了一个在线协作小工具上线第一天晚上服务器直接崩了用户疯狂吐槽“怎么画着画着就断了” 那一晚我盯着监控面板才真正明白——WebSocket 的坑不在握手而在长连接的战场上。 本文摘要从 FastAPI 实战出发分享在生产环境中用 WebSocket 踩过的坑、填坑的方案以及那些容易忽略的注意事项。读完你不仅能跑通 Demo还能让连接更稳定心里更有底。 FastAPI 实战WebSocket 使用避坑指南让你的长连接稳如老狗 这篇你会得到什么 第一部分WebSocket 的本质用一个餐厅的故事讲透 第二部分FastAPI 集成 WebSocket 的最小实战带代码 第三部分5 个最常见翻车点及解决方案心跳、认证、并发、部署、异常 第四部分老程序员的碎碎念经验总结 互动 1. 先从 WebSocket 是什么聊起一个餐厅的比喻传统的 HTTP 请求就像你去餐厅点菜你喊一声“服务员来份宫保鸡丁”然后服务员跑去后厨把菜端给你一次交易结束。你要再点个米饭又得喊一次。而 WebSocket 呢它就像你直接在餐厅包了个雅间服务员就站在你桌旁随时听你吩咐“加点水”、“拿头蒜”、“结账” —— 服务员一直在线随时响应省去了反复呼叫的过程。FastAPI 对 WebSocket 的支持非常 Pythonic用起来很顺手但正因为顺手容易忽略背后那些“服务员也得休息”、“包间太多会拥挤”的现实问题。⚡ 2. 最小实战一个简单的聊天 echo 服务先来个最基础的看看 FastAPI 里 WebSocket 长啥样。下面的代码实现了一个 echo 功能客户端发什么我就原样返回什么。/* by 01022.hk - online tools website : 01022.hk/zh/editor.html */ from fastapi import FastAPI, WebSocket, WebSocketDisconnect app FastAPI() app.websocket(/ws) async def websocket_endpoint(websocket: WebSocket): await websocket.accept() try: while True: # 接收客户端消息 data await websocket.receive_text() # 原样返回 await websocket.send_text(f服务端收到: {data}) except WebSocketDisconnect: print(客户端断开连接) except Exception as e: print(f发生异常: {e}) # 记得主动关闭连接 await websocket.close()看着是不是很简单✨ 但这里已经藏着一个坑如果客户端异常断开比如网络闪断receive_text()会抛出WebSocketDisconnect你得捕获它否则程序会崩溃。我曾经没写这个 try结果 uvicorn 进程直接挂掉教训惨痛。 3. 五个让你凌晨三点爬起来填的坑附解决方案 3.1 连接自动断开因为没有心跳很多云服务商比如阿里云、AWS的负载均衡器如果一段时间内没有数据传输会认为连接空闲而把它掐掉。这个时间通常是 60 秒左右。解决方案服务端和客户端都要有心跳机制。最简单的做法是客户端每隔 30 秒发一个 ping 帧或者自定义心跳消息服务端收到后回复 pong。当初我偷懒没做心跳用户画图时停顿超过 1 分钟就掉线被产品经理追着打。 后来加了个定时器世界安静了。/* by 01022.hk - online tools website : 01022.hk/zh/editor.html */ # 服务端处理心跳的伪代码 async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: try: # 设置接收超时如果一段时间没收到任何消息主动发心跳探测 data await asyncio.wait_for(websocket.receive_text(), timeout30) # 处理正常消息 except asyncio.TimeoutError: # 30 秒没收到消息主动发送 ping 探测 await websocket.send_text(__ping__) # 自定义心跳 # 如果客户端没响应会在下一次循环触发 WebSocketDisconnect 3.2 WebSocket 握手时如何携带 TokenWebSocket 的握手是 HTTP 请求所以可以在 URL 参数或者 Header 里带 token。但千万不要在路径里明文传 token会记在日志里推荐的做法用Sec-WebSocket-Protocol或者 Header 里的Authorization。FastAPI 的依赖注入也支持 WebSocket你可以写一个依赖来校验。from fastapi import WebSocket, WebSocketException, status async def get_cookie_or_token(websocket: WebSocket): # 从 query 参数或 header 取 token示例从 query 取 token websocket.query_params.get(token) if token ! secret: await websocket.close(codestatus.WS_1008_POLICY_VIOLATION) raise WebSocketException(认证失败) return token app.websocket(/ws) async def websocket_endpoint(websocket: WebSocket, token: str Depends(get_cookie_or_token)): await websocket.accept() # ... 3.3 连接数一高服务就卡死每个 WebSocket 连接都会占用一个系统文件描述符和内存。默认的 uvicorn 单进程能支撑的连接数有限取决于你机器配置。如果直接裸跑内存可能会被慢慢吃光。解决方案 用gunicorn uvicorn workers启动多进程注意设置适当的 worker 数量一般 CPU 核心数 * 2。 如果广播消息频繁不要用简单的全局循环给所有连接发可以用asyncio.gather并发发送但注意控制并发数防止突发流量把 CPU 打满。 考虑使用 Redis 等中间件做消息分发特别是多进程模式下一个进程不知道另一个进程管理的连接需要借助外部广播。⚠️ 线上教训我曾用单进程跑了 5000 个连接结果内存占用 2GB频繁 GC最后用--workers 4解决了但广播又成了新问题后来引入了 Redis pub/sub。 3.4 服务重启时用户瞬间掉线怎么办当你部署新版本需要重启服务所有 WebSocket 连接会被粗暴关闭。用户会看到“连接已断开”。这很不优雅。解决方案利用 uvicorn 的lifespan事件在关闭前主动通知客户端比如发一条“服务即将维护”的消息并等待几秒再关闭。也可以配合负载均衡的 draining 机制。# 在 shutdown 事件里做清理 app.on_event(shutdown) async def shutdown_cleanup(): # 遍历所有活跃连接发下线通知 for connection in active_connections: try: await connection.send_text(server going down, reconnect later) except: pass # 等 1 秒让消息发出去 await asyncio.sleep(1) 3.5 文本还是二进制JSON 还是自定义WebSocket 支持文本和二进制帧。如果你们前后端约定用 JSON记得处理解析异常。我曾经因为前端发了个非法的 JSON服务端没捕获json.JSONDecodeError直接导致连接崩溃。稳健的做法统一用receive_json()并捕获异常给客户端返回错误码而不是断开连接。 4. 程序媛的碎碎念从能用→好用→稳如泰山WebSocket 的上手门槛确实低但想在生产环境跑得稳你需要考虑这些✅ 监控每一条连接的存活时间、收发消息数量最好都能通过 metrics 暴露出来比如用 Prometheus。✅ 限流单个用户发消息太快怎么办可以用漏桶或令牌桶限制频率防止被恶意攻击。✅ 断线重连客户端一定要有自动重连机制指数退避策略避免同时重连造成服务器压力。✅ 测试用websockets库写脚本模拟数千个连接压测一下你的服务看资源占用和响应延迟。我还记得有一次我忘记设置max_size限制客户端传了个超大的消息直接把内存撑爆了。后来在 accept 之前加上websocket.max_size 1_048_5761MB世界又清净了。老朋友今天的分享就到这里。如果你也在 FastAPI 里踩过 WebSocket 的坑或者有什么独家秘笈欢迎留言区切磋。⭐️ 觉得有用的话点个赞再走呗这样我下回才有动力写出更多FastAPI 避坑指南。当然关注我也可以毕竟你不知道我下次又会因为什么骚操作给你带来新的实战经验
node js 性能处理 优化 Node.js 性能是一个系统工程,涉及从代码逻辑到系统架构的多个层面。由于 Node.js 是单线程且基于事件循环的,优化的核心思路通常是:减少阻塞主线程、优化 I/O 处理、提升并发能力。 以下是整理好的优化策略,按优先级和维度分… 2026/7/8 16:30:16
从此告别拖延,AI论文网站 千笔·专业论文写作工具 VS 文途AI 随着人工智能技术的迅猛发展,AI辅助写作工具正逐步成为高校学生完成毕业论文的重要帮手。越来越多的学生开始借助这些工具提升写作效率、优化内容结构,尤其是在面对繁重的论文任务时,AI的介入让学术写作变得更加高效与可控。然而,… 2026/7/14 0:07:16
新手也能上手 10个降AIGC平台测评:专科生降AI率必备攻略 在当前学术写作日益依赖AI工具的背景下,如何有效降低论文的AIGC率、去除AI痕迹并同时保持文章语义通顺,成为许多专科生面临的难题。随着高校对AI生成内容的识别技术不断升级,传统的复制粘贴或简单改写已难以满足查重要求。因此,越… 2026/7/15 10:50:18
【2014-01-27】cocos2dx学习笔记:CCNode回调流程 [历史归档] 本文原发布于 cstriker1407.info 个人博客,内容为历史存档,仅供参考。 发布时间: 2014-01-27 | 标题:cocos2dx学习笔记:CCNode回调流程 | 分类: 编程 / C &&… 2026/7/16 5:44:33
C++ priority_queue 深度解构:从堆算法到容器适配器实现 1. 项目概述:从“会用”到“懂它”,一次对 priority_queue 的深度解构如果你用过 C STL 里的priority_queue,大概率会觉得它很方便:push一个元素,pop出来的总是当前“最大”或“最小”的那个。面试官问你它的底层是什么… 2026/7/16 5:42:32
集成过压保护模拟开关的设计与应用实践 1. 为什么我们需要重新思考保护电路设计在电子系统设计中,过压保护一直是个让人头疼的问题。传统方案通常采用TVS二极管、保险丝、继电器等分立器件搭建保护电路,这种方案我已经用了十几年。但最近在做一个工业传感器项目时,这套方案让我栽了… 2026/7/16 5:42:32
电子病历自动生成与结构化:AI模型赋能医疗信息管理新路径 电子病历自动生成与结构化:AI模型赋能医疗信息管理新路径 在医疗信息化不断推进的当下,电子病历作为医疗数据的重要载体,其质量与利用效率直接影响着医疗服务的质量和医疗研究的进展。电子病历自动生成与结构化技术,借助AI模型的力… 2026/7/16 5:40:31
二维数组对角线操作实战:从坐标规律到焦点遍历的双解剖析 1. 二维数组对角线操作入门:从概念到实战第一次接触二维数组对角线操作时,我也曾被那些坐标规律绕得头晕。直到在算法比赛中因为对角线问题丢分后,才真正静下心来研究这个看似简单却暗藏玄机的话题。二维数组对角线操作是信息学竞赛和算法面试… 2026/7/16 5:40:31
题解:AcWing 237 程序自动分析 【题目来源】 AcWing:237. 程序自动分析 - AcWing题库 【题目描述】 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。 考虑一个约束满足问题的简化版本:假设 x1,x2,x3,…x_1,x_2,x_3,…x1,x2,x3,… 代表程… 2026/7/16 5:36:29
A--10 Codex Review与GitHub PR工作流实战指南:从代码审查到安全合并 摘要:本文系统讲解如何利用Codex App的Review功能与GitHub PR工作流,实现从代码修改到安全合并的完整流程。涵盖Review面板深度使用、/review命令实战、GitHub Connector配置、PR描述撰写技巧,以及常见问题排查方法。通过多个实战案例和流程图,帮助开发者建立高效的AI辅助代… 2026/7/16 0:00:26
HAM未来路线图:下一代高可用迁移技术的发展方向与展望 HAM未来路线图:下一代高可用迁移技术的发展方向与展望 【免费下载链接】ham Based on the remote memory access capability and high bandwidth of the UB, deterministic duration virtual machine live migration is achieved, addressing planned downtime issu… 2026/7/16 0:04:27
月球是否是从地球分离出去的?——容度原理解释 月球是否是从地球分离出去的?——容度原理解释一、月球起源的“三大假说”与容度原理的重新审视月球起源的三大假说——捕获说(月球是太阳系中独立的星体,被地球引力捕获)、共生说(月球与地球同时从原始星云中形成&… 2026/7/16 0:06:27
Git reset 与 revert 深度对比:5个关键差异与 3 种典型应用场景 Git Reset 与 Revert 深度对比:5个关键差异与3种典型应用场景在团队协作开发中,代码版本管理如同行走钢丝——一步失误可能导致整个项目陷入混乱。作为Git进阶用户,你是否曾在深夜面对错误的提交束手无策?是否在强制推送后收到同事… 2026/7/13 8:31:55
GitHub 学生包申请避坑:5个常见失败原因与开发者工具调试方案 GitHub 学生包申请技术排障指南:5个高频失败场景与开发者工具实战方案第一次尝试申请GitHub学生包时,我盯着屏幕上那个不断转圈的加载动画整整15分钟,最终只等来了一行冰冷的错误提示。这可能是许多开发者共同的经历——明明按照教程操作&… 2026/7/16 3:47:53
冒烟测试用例设计规范:5%-10%覆盖率下的3类核心场景与执行标准 冒烟测试用例设计的黄金法则:5%-10%覆盖率下的精准筛选策略在快节奏的敏捷开发环境中,冒烟测试作为质量保障的第一道防线,其重要性不言而喻。当测试资源有限而时间紧迫时,如何从海量测试用例中精准筛选出那关键的5%-10%࿰… 2026/7/14 5:09:41