Ubuntu22.04部署Flask Socket应用(Nginx+Gunicorn)遇404错误
问题排查与解决方法
核心问题分析
本地使用gevent.pywsgi.WSGIServer搭配WebSocketHandler能正常运行websocket,是因为flask_sockets库本身基于gevent-websocket实现;而服务器端用gunicorn + eventlet worker时,两者生态不兼容,导致/media这个websocket路由无法被正确注册,最终返回404。
同时你的gunicorn启动命令存在参数冲突:-w1和--workers 3重复(-w是--workers的简写),会导致实际启动3个worker,这对websocket长连接场景也不友好。
具体解决步骤
方案1:改用gunicorn+gevent worker(推荐,无需修改代码)
因为flask_sockets依赖gevent生态,直接用gevent作为gunicorn的worker类即可:
- 确保虚拟环境中安装gevent:
/root/test-socket/myenv/bin/pip install gevent
- 修改systemd服务文件
/etc/systemd/system/demo.service的ExecStart行:
ExecStart=/root/test-socket/myenv/bin/gunicorn --worker-class gevent --workers 1 --bind 127.0.0.1:5000 app:app
注:websocket是长连接,建议只启动1个worker,避免负载均衡导致的连接异常。
- 重启systemd服务:
systemctl daemon-reload systemctl restart demo.service
方案2:验证应用本身的websocket响应
在服务器本地直接测试应用端口,排除Nginx代理的影响:
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: localhost" -H "Origin: http://localhost" http://127.0.0.1:5000/media
- 如果返回404:说明应用本身未正确注册路由,确认方案1的配置是否生效。
- 如果返回
101 Switching Protocols:说明应用正常,可检查Nginx的proxy_params文件是否覆盖了必要请求头。
方案3:替换为eventlet兼容的websocket库(需修改代码)
如果坚持使用eventlet,需要替换flask_sockets为支持eventlet的库,比如flask-socketio:
- 安装依赖:
/root/test-socket/myenv/bin/pip install flask-socketio eventlet
- 修改
app.py代码适配flask-socketio:
import json from flask import Flask, jsonify from flask_socketio import SocketIO, on from flask_cors import CORS app = Flask(__name__) CORS(app) socketio = SocketIO(app, cors_allowed_origins="*") @app.route("/hello", methods=['GET', 'POST']) def hello(): print("testing") return jsonify({"message": "Success"}) @socketio.on('message', namespace='/media') def handle_media_message(message): print(f"Media WS: {message}") packet = json.loads(message) print(packet) if __name__ == '__main__': socketio.run(app, host='127.0.0.1', port=5000)
- 修改gunicorn启动命令:
ExecStart=/root/test-socket/myenv/bin/gunicorn --worker-class eventlet --workers 1 --bind 127.0.0.1:5000 app:app
- 重启服务测试。
内容的提问来源于stack exchange,提问作者arun n a
相关产品推荐
相关产品推荐

