Flask+uWSGI+Nginx环境下WebSocket连接失败问题求助
Flask-uWSGI-WebSocket 404错误修复方案
问题场景
开发Flask API时集成WebSocket,使用flask-uwsgi-websocket包,常规HTTP路由正常,但WebSocket路由/api/websocket/echo返回404,连接迅速断开。相关配置如下:
main.py代码
from gevent.monkey import patch_all patch_all() # pylint: disable=wrong-import-position from flask_uwsgi_websocket import GeventWebSocket # noqa: E402 # More imports... # pylint: enable=wrong-import-position from flask import Flask app = Flask(__name__) websocket = GeventWebSocket(app) # 常规HTTP路由定义 @websocket.route('/api/websocket/echo') def echo(w_s): """WebSocket echo服务""" print(1) print(w_s) print(2) while True: msg = w_s.receive() w_s.send(msg) if __name__ == '__main__': app.run(debug=True, threaded=True, gevent=100)
config-uwsgi.ini配置
[uwsgi] app = main module = %(app) callable = app socket = /tmp/module_name.sock chdir = /path_to_module chmod-socket = 666 virtualenv = /path_to_module/venv enable-threads = true http-websockets = true master = true processes = 1 die-on-term = true
config-nginx.conf配置
server { listen 80; listen [::]:80; listen 443 ssl; server_name some.server.com; ssl_certificate /etc/letsencrypt/live/some.server.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/some.server.com/privkey.pem; server_tokens off; location / { include uwsgi_params; uwsgi_pass unix:/tmp/module_name.sock; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_read_timeout 3600s; proxy_send_timeout 3600s; } }
错误日志
Jan 09 22:23:25 ip-192-168-1-50 uwsgi[242836]: [pid: 242836|app: 0|req: 5/5] 189.XXX.XXX.XXX () {52 vars in 914 bytes} [Mon Jan 9 22:23:25 2023] GET /api/websocket/echo => generated 207 bytes in 0 msecs (HTTP/1.1 404) 2 headers in 87 bytes (1 switches on core 0)
修复步骤
1. 修正Nginx的头传递指令
当前Nginx使用proxy_set_header,但该指令仅适配proxy_pass场景,而你使用的是uwsgi_pass,需替换为uwsgi_set_header,同时建议单独为WebSocket路径配置规则,避免影响常规路由:
修改后的config-nginx.conf:
server { listen 80; listen [::]:80; listen 443 ssl; server_name some.server.com; ssl_certificate /etc/letsencrypt/live/some.server.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/some.server.com/privkey.pem; server_tokens off; # 单独处理WebSocket路由 location /api/websocket/ { include uwsgi_params; uwsgi_pass unix:/tmp/module_name.sock; uwsgi_set_header Upgrade $http_upgrade; uwsgi_set_header Connection "Upgrade"; uwsgi_read_timeout 3600s; uwsgi_send_timeout 3600s; } # 处理常规HTTP路由 location / { include uwsgi_params; uwsgi_pass unix:/tmp/module_name.sock; } }
2. 完善uWSGI的Gevent支持
确保uWSGI启用Gevent事件循环,在config-uwsgi.ini中添加gevent参数:
[uwsgi] # 原有配置保留 gevent = 100 http-websockets = true enable-threads = true master = true processes = 1 # 原有配置保留
同时确认安装带Gevent支持的uWSGI:
pip install uwsgi[gevent]
3. 确认代码导入顺序
确保gevent.monkey.patch_all()在所有其他导入之前执行(你的代码已符合要求,无需修改),这是Gevent协程正常工作的必要前提。
测试验证
使用wscat工具测试WebSocket连接:
# 安装wscat npm install -g wscat # 发起WebSocket连接 wscat -c wss://some.server.com/api/websocket/echo
连接成功后发送消息,应收到对应的echo返回。
内容的提问来源于stack exchange,提问作者Dykeiichi
相关产品推荐
相关产品推荐

