flask原生不支持websocket,推荐组合flask+python-socketio处理实时通信,或用websockets库另起异步服务;需注意版本匹配、nginx代理配置、空闲超时及前端重连策略。

Flask 本身不支持 WebSocket,得换方案
Flask 原生只处理 HTTP 请求,flask 模块里根本没有 WebSocket 类或路由装饰器。硬要在 Flask 里塞 WebSocket,要么用 gevent-websocket(已多年未维护),要么自己套一层 eventlet 或 gevent 并改写 WSGI server——但这样会破坏 Flask 的轻量定位,且容易在生产环境出并发问题。
更实际的做法是:用 Flask 做静态资源和 API 接口(比如获取历史数据、配置项),把实时通信交给真正为 WebSocket 设计的库。
- 推荐组合:
Flask+Socket.IO(即python-socketio),它兼容长轮询降级,开发体验接近原生 WebSocket,且能和 Flask 共享 session - 如果追求极简和纯 WebSocket 协议(比如对接前端
new WebSocket()),直接上websockets库,另起一个异步服务端口(如8765),和 Flask 的5000端口并存 - 别碰
Flask-SocketIO的旧版文档——它依赖已废弃的flask-socketio0.x,新版统一用python-socketio
用 python-socketio 实现监控数据推送
核心逻辑是:后端定时采集指标(CPU、内存、自定义状态),通过 socketio.emit() 推给所有连接的客户端。前端用 socket.io-client 监听事件,触发图表更新。
关键点不是“怎么连”,而是“怎么推得稳”:
- 不要在主线程里用
time.sleep()轮询——会阻塞整个 event loop;改用socketio.start_background_task()启动协程任务 - 避免高频推送压垮浏览器:监控看板通常 1–3 秒刷新一次,设个
last_emit_time缓存,差值小于阈值就跳过 - 推送时带上时间戳字段,前端用它对齐动画帧,而不是依赖
setInterval,否则网络抖动会导致图表卡顿 - 示例片段:
def background_monitor(): while True: socketio.sleep(2) # 非 time.sleep() data = {"cpu": psutil.cpu_percent(), "ts": time.time()} socketio.emit("metric_update", data, broadcast=True)
前端连接 Socket.IO 时常见 400/404 错误
错误信息像 GET http://localhost:5000/socket.io/?EIO=4&transport=polling&t=... 400 (Bad Request),本质是前后端版本不匹配或路径没对齐。
- 确认 Python 端装的是
python-socketio[client](非Flask-SocketIO);前端引入的 JS 必须是https://cdn.socket.io/4.7.2/socket.io.min.js(版本号要和 Python 库一致,查pip show python-socketio) - 默认路径是
/socket.io/,若 Flask 用了反向代理(如 Nginx),必须透传 Upgrade 头,并显式配置socketio = SocketIO(app, cors_allowed_origins="*") - 别在前端写
io("http://localhost:5000")——如果页面本身就是http://localhost:5000/dashboard,直接io()即可,否则跨域失败 - 调试时打开浏览器 Network 面板,过滤
socket.io,看 polling 请求是否返回 200 和有效 sid;如果一直 400,大概率是 query 参数被代理截断或后端未启用 async_mode
生产部署时 WebSocket 连接意外断开
本地跑得好,一上服务器就频繁掉线,90% 是基础设施层主动切断了空闲长连接。
- Nginx 默认
proxy_read_timeout是 60 秒,WebSocket 空闲超时就会断开;必须在 location 块里加:proxy_read_timeout 300; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
- 云服务商(如 AWS ALB、腾讯云 CLB)的负载均衡器也有空闲超时设置,需调大到 300 秒以上,且确保开启 WebSocket 支持开关
- 客户端需实现重连逻辑:用
socket.on("disconnect", () => setTimeout(() => socket.connect(), 5000)),别依赖自动重连(Socket.IO 的reconnection选项在监控场景下容易堆积未确认消息) - 如果用
websockets库直连,记得在服务端ping_interval=20,否则某些防火墙会静默丢弃连接
监控看板真正的难点不在“连上”,而在“连得久、推得准、断得清”。很多团队卡在 Nginx 配置或前端重连策略上,反复刷新页面才看到数据,其实问题根本不在 Python 代码里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











