Flask不支持原生WebSocket,应使用Flask-SocketIO;需配置manage_session=True并前端携带凭证以共享session;广播消息须设include_self=False;Nginx部署时必须透传Upgrade和Connection头。

Flask 里直接用原生 WebSocket?别试了,flask 本身不支持
Flask 没有内置 WebSocket 支持,硬套 request.environ.get("wsgi.websocket") 这类方式只在极少数 WSGI 服务器(比如 gevent-websocket)下能跑,而且和 Flask 路由、上下文、请求生命周期严重脱节。你写出来的代码大概率在本地调试通,一上 gunicorn 或 nginx 就 502 或连接被重置。
真正轻量又靠谱的路径只有一条:用 Flask-SocketIO —— 它不是“纯 WebSocket”,但会自动降级到长轮询(polling),兼容老旧环境;同时保留了 Flask 的路由风格和 session、g 等上下文能力。
-
Flask-SocketIO底层依赖python-socketio和异步服务器(eventlet或gevent),不装对应并发库会启动失败,报错类似RuntimeError: You need to use the eventlet server - 开发阶段用
eventlet最省事:pip install flask-socketio eventlet,然后启动时加async_mode="eventlet" - 别用
threading模式做生产部署,它无法处理真正的并发连接,只是模拟,撑不过 10 个用户
怎么让 SocketIO 和 Flask 共享 session / 用户状态
很多人卡在这儿:前端发来消息,后端想查当前登录用户的 user_id,结果 session 是空的,或者每次连接都是新 session。
根本原因是:WebSocket 连接建立时不会自动携带 Cookie(尤其跨域时),而 Flask-SocketIO 默认不启用 session 同步。必须手动配置并显式读取。
立即学习“Python免费学习笔记(深入)”;
- 服务端初始化要传
manage_session=True:SocketIO(app, manage_session=True, async_mode="eventlet") - 前端连接时得带上凭证:如果用
io(),需加{ withCredentials: true };如果是跨域,后端还得配cors_allowed_origins -
session在@socketio.on("connect")里不可靠,建议改用@socketio.on("auth")手动传 token,再解码存到flask.g或自定义连接映射字典里 - 别依赖
request.sid做用户绑定——它是连接 ID,不是用户 ID;一个用户开两个标签页,会有两个sid
广播消息到大厅所有人,但别发回给自己
实现“大厅聊天室”最常写的逻辑就是:用户 A 发一条消息,除 A 外所有人收到。但新手常误用 emit(..., broadcast=True),结果自己也收到了,造成消息重复渲染。
关键在 include_self=False 这个参数,默认是 True,文档里藏得深,不注意就踩坑。
- 正确写法:
socketio.emit("message", {"text": txt}, broadcast=True, include_self=False) - 如果只想发给某房间(比如
"lobby"),用room="lobby"+include_self=False,别混用namespace和room逻辑 - 房间名不要带斜杠或点号,
socketio.join_room("user.123")可能触发内部解析异常;用下划线或连字符更稳:"user_123" - 广播性能没问题,
Flask-SocketIO内部做了连接遍历优化;但别在循环里反复emit,应合并数据一次性推
部署时 nginx 报 400 或连接立即断开
这是线上最典型的故障:开发机一切正常,一上 nginx 就连不上,控制台显示 WebSocket connection to 'wss://...' failed,日志里 nginx 记着 400 Bad Request。
根本原因就两个:HTTP 协议升级头没透传、SSL 配置不匹配。
- nginx 配置里必须显式透传
Upgrade和Connection头:proxy_set_header Upgrade $http_upgrade;<br>proxy_set_header Connection "upgrade";
- 如果用 HTTPS,确保
wss://前端连接地址和 nginx 的server_name一致,且证书有效;自签名证书会导致浏览器直接拒连 -
location /socket.io的路径必须和 Flask 初始化时的path参数一致(默认是/socket.io),否则握手 404 - 别在 nginx 里加
proxy_buffering off之类乱七八糟的优化,Flask-SocketIO自己会处理流控
复杂点在于:同一个域名下既要跑普通 HTTP 接口,又要跑 SocketIO,路径隔离和 header 透传必须精确对齐,差一个字母或少一行配置,连接就静默失败。这时候看 nginx error log 比看 Flask 日志还管用。










