uWSGI+Nginx部署Flask OpenApi服务返回500错误求助
问题描述
基于Flask+Connexion构建的OpenAPI Web服务在开发环境运行正常,部署到uWSGI+Nginx生产环境时,所有组件启动状态无异常,但POST请求全部返回HTTP 500,请求未进入业务逻辑层,uWSGI仅输出通用错误处理日志,无明确报错栈。
现有配置信息
服务初始化代码
import connexion from flask_cors import CORS from src.middlewares import Log as midLog from src.middlewares import DB as midDb import utils from web.doc import bp_doc # Instance a Flask server with Connexion library that validate openAPI app = connexion.FlaskApp(__name__, specification_dir='specification/') # DB init app.app.wsgi_app = midDb.DB(app.app) # Load OPEN API doc utils.load_openapi() # OpenAPI doc verif + CORS + Doc app.add_api(sfile.File.path("tmp","config.adhoc","openapi.yaml"), options = {"swagger_ui": False},validate_responses=True,base_path="/") CORS(app.app) # Build CORS Header app.app.register_blueprint(bp_doc,url_prefix='/doc') # Register Blueprint # Active Log app.app.wsgi_app = midLog.Log(app.app,DEBUG) #app.run()
uWSGI ini配置
[uwsgi] module=wbsvc:application wsgi-file=wbsvc.py master = true processes = 10 buffer-size=65535 socket = wbsvc.sock chmod-socket = 660 vacuum = true die-on-term = true
Nginx配置
server { listen 80; server_name localhost; client_max_body_size 10M; keepalive_timeout 60s; client_body_timeout 60s; sendfile on; client_body_buffer_size 20m; location /wbsvc { include uwsgi_params; uwsgi_pass unix:/home/webservice/svc/wbsvc.sock; } }
systemd服务配置
[Unit] Description=uWSGI configuration file for the web service After=network.target [Service] User=web_services Group=www-data WorkingDirectory=/home/webservice/svc/ Environment="PATH=/home/webservice/svc/ws_env/bin" ExecStart=/home/webservice/svc/ws_env/bin/uwsgi --ini ws.ini [Install] WantedBy=multi-user.target
错误日志
ERROR HANDLING [pid: 17399|app: 0|req: 1/1] 81.250.236.200 () {40 vars in 734 bytes} [Fri Jul 8 11:52:24 2022] POST <url requested> => generated 106 bytes in 17 msecs (HTTP/1.1 500) 4 headers in 135 bytes (2 switches on core 0)
运行环境版本
- 操作系统:Ubuntu 18.04 LTS
- Python版本:3.8
- Nginx版本:1.14.0
- uWSGI版本:2.0.20
- Flask版本:2.1.2
根因与修复步骤
1. 修复uWSGI入口对象错误
connexion.FlaskApp是Connexion框架的包装实例,不是标准WSGI可调用对象,uWSGI需要的入口是其内部封装的原生Flask实例,即app.app。当前配置中未定义名为application的顶层对象,uWSGI加载应用时会直接失败。
修复方式:在服务代码末尾(不要放入if __name__ == '__main__'判断块)添加如下代码,同时删除所有无判断包裹的app.run()调用,避免触发Flask开发服务器警告:
application = app.app
2. 修复中间件覆盖问题
当前代码两次直接给app.app.wsgi_app赋值,第二次注册的Log中间件会完全覆盖第一次注册的DB中间件,导致数据库中间件不生效,涉及数据库操作的POST请求会在中间件层直接抛出异常,无法进入业务逻辑。
修复方式:按照WSGI洋葱模型顺序包装中间件,每一层中间件初始化时传入上一层的wsgi_app对象,而非直接传入Flask实例、直接覆盖属性:
# DB 中间件作为内层 app.app.wsgi_app = midDb.DB(app.app.wsgi_app) # 路由注册、CORS、蓝图注册等逻辑保持不变 # Log 中间件作为外层包裹 app.app.wsgi_app = midLog.Log(app.app.wsgi_app, DEBUG)
3. 修复Nginx路径转发错误
当前Nginx配置中location匹配前缀为/wbsvc,但Connexion配置的API根路径为/,请求转发到uWSGI时会携带/wbsvc前缀,Flask路由表中无对应匹配规则,会在路由层直接抛出错误。
修复方式:修改Nginx location配置,添加路径重写规则,转发前剥离路径前缀:
location /wbsvc { include uwsgi_params; uwsgi_param SCRIPT_NAME /wbsvc; rewrite ^/wbsvc/(.*)$ /$1 break; uwsgi_pass unix:/home/webservice/svc/wbsvc.sock; }
4. 辅助排查配置
在uWSGI的ini配置中添加如下参数,开启5xx错误日志捕获,直接将Python层的异常栈打印到uWSGI日志中,方便定位剩余问题:
catch-exceptions = true log-5xx = true enable-threads = true
同时确认Nginx运行用户属于www-data用户组,拥有uWSGI socket文件的读写权限,避免出现权限类错误。
验证流程
- 先跳过Nginx,本地用uWSGI直接启动服务,通过绑定端口的方式发送POST请求,确认请求可以正常到达业务逻辑层
- 依次重启uWSGI服务、Nginx服务,先访问
/wbsvc/doc路径验证GET请求正常,再测试POST业务接口 - 观察uWSGI错误日志,若仍有报错可根据打印的异常栈进一步定位
内容的提问来源于stack exchange,提问作者Simon

