Heroku部署Flask+SocketIO报400 BAD REQUEST及eventlet错误
问题修复方案
核心错误点
- 客户端socket.io 4.5版本与旧版flask-socketio协议不兼容,触发400 BAD REQUEST
- eventlet 0.30.2版本与gunicorn、高版本Python适配存在bug,导致
class uri 'eventlet' invalid or not found报错 - Procfile启动参数、SocketIO初始化参数缺失,消息广播未开启,无法实现多用户同步
- 客户端重复初始化socket连接,跨域参数未配置
具体修复步骤
- 固定依赖版本
替换requirements.txt中相关依赖为以下兼容版本:
Flask==2.0.3 flask-socketio==5.3.6 python-socketio==5.8.0 python-engineio==4.7.1 eventlet==0.33.3 gunicorn==20.1.0 flask-cors==3.0.10
该版本组合下,服务端完美兼容4.x版本socket.io客户端,无需降级客户端到2.3.x版本。eventlet 0.30.2存在worker类识别bug,升级到0.33.3即可解决。
- 修正服务端代码
调整SocketIO初始化配置,补充广播参数:
from flask import Flask, render_template, url_for, redirect, session, request, jsonify from flask_socketio import SocketIO from flask_cors import CORS app = Flask(__name__) app.config['SECRET_KEY'] = '替换为你的自定义密钥' CORS(app, supports_credentials=True) # 明确指定异步模式、跨域规则 socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet') # 其余业务路由代码保持不变 ... @socketio.on('message') def handle_msg(msg): # 必须加broadcast=True才能把消息推送给所有连接用户,否则仅发消息本人能收到 socketio.send('Syncing...', broadcast=True) if __name__ == '__main__': socketio.run(app)
- 修正Procfile启动命令
替换Procfile内容为以下配置:
web: gunicorn --worker-class eventlet -w 1 main:app
eventlet模式下SocketIO仅支持单worker运行,多worker会导致消息广播失效。
- 修正客户端连接逻辑
删除重复的socket初始化代码,改为单次初始化传参:
// 移除空参io()初始化、单独connect调用,直接在初始化时传入服务端地址和配置 export const socket = io('https://proman-code-cool.herokuapp.com/', { transports: ['websocket', 'polling'], withCredentials: true }); function init() { // 其余初始化逻辑保持不变 //live sync socket.on('message', function(msg) { console.log(msg); boardsManager.reloadBoards(userId); }); } init();
- Heroku平台配置
部署后在本地终端执行以下命令,开启平台会话粘滞支持,避免连接漂移断连:
heroku features:enable http-session-affinity -a proman-code-cool
内容的提问来源于stack exchange,提问作者Deadjim
相关产品推荐
相关产品推荐

