AWS Elastic Beanstalk部署Flask-SocketIO后Socket连接失败及代理配置问题
Flask-SocketIO在AWS Elastic Beanstalk无法连接的解决方案
问题根源
- 代理配置报错:你用的
ProxyServer: 'none'仅适用于旧版Amazon Linux(AMI),新版Amazon Linux 2的EB Python平台不支持该配置,因此部署时触发错误。 - Socket连接失败:默认Apache代理未转发WebSocket所需的
Upgrade和Connection请求头,导致握手失败;同时本地与EB的端口配置不匹配,也会引发连接异常。
分步解决
一、修复代理配置(二选一)
方案1:保留Apache代理,添加WebSocket转发规则
修改.ebextensions/wsgi_custom.conf,补充WebSocket转发逻辑:
files: "/etc/httpd/conf.d/wsgi_custom.conf": mode: "000644" owner: root group: root content: | WSGIApplicationGroup %{GLOBAL} # 转发WebSocket请求到gunicorn RewriteEngine On RewriteCond %{HTTP:Upgrade} =websocket [NC] RewriteRule /(.*) ws://localhost:8000/$1 [P,L] RewriteCond %{HTTP:Upgrade} !=websocket [NC] RewriteRule /(.*) http://localhost:8000/$1 [P,L] packages: yum: python3-devel: [] gcc: [] gawk: [] polkit: [] gcc-c++: [] make: []
该配置让Apache识别WebSocket请求,自动转发到gunicorn监听的8000端口。
方案2:禁用代理,让gunicorn直接监听80端口
- 删除之前错误的
ProxyServer: 'none'配置,在.ebextensions中添加端口设置:
option_settings: aws:elasticbeanstalk:environment:process:default: Port: "80" HealthCheckPath: "/hello_world"
- 修改Procfile,指定gunicorn监听80端口:
web: gunicorn --worker-class eventlet -w 1 --bind 0.0.0.0:80 app:app
这样EB会跳过Apache代理,直接把流量打到gunicorn服务上。
二、修正SocketIO相关代码
- 明确指定异步模式:在
__init__.py中给SocketIO实例加上async_mode='eventlet',避免自动检测出错:
from flask import Flask from flask_cors import CORS from flask_socketio import SocketIO # 强制使用eventlet作为异步引擎 socketio = SocketIO(cors_allowed_origins="*", async_mode='eventlet') def create_app(config_file='config.py'): app = Flask(__name__, static_url_path='/fx_app/media', static_folder='media') CORS(app, resources={r"/socket.io/*": {"origins": "*"}}) app.config.from_pyfile(config_file) with app.app_context(): socketio.init_app(app) from .socket_events import configure_socket_events configure_socket_events(socketio) return app
- 本地启动改用socketio.run:修改
app.py的启动逻辑,确保本地开发也用eventlet运行:
from fx_app import create_app, socketio app = create_app() @app.route('/hello_world') def hello_world(): return 'Hello, World!' if __name__ == '__main__': # 用socketio.run替代app.run,保证eventlet正确加载 socketio.run(app, host='0.0.0.0', port=8081, debug=True, load_dotenv=True)
- 锁定依赖版本:在
requirements.txt中指定兼容的包版本,避免依赖冲突:
flask==2.3.3 flask-socketio==5.3.5 eventlet==0.33.3 flask-cors==4.0.0 gunicorn==21.2.0
三、验证部署
- 部署后查看EB日志,确认gunicorn以eventlet worker启动,监听端口和配置一致。
- 客户端连接时,直接用EB环境域名(比如
https://your-env.elasticbeanstalk.com),不要手动加端口。 - 检查浏览器控制台的网络请求,确认
/socket.io/的请求返回200,WebSocket握手状态码为101。
内容的提问来源于stack exchange,提问作者Umar Farooq
相关产品推荐
相关产品推荐

