Flask+Flask-PyMongo uWSGI部署遇MongoClient fork前创建警告如何解决
问题根因
你遇到的警告是uWSGI默认工作模式导致的:uWSGI会先在master进程加载完整的应用实例,再fork出多个子进程处理请求。如果master进程加载应用的过程中就创建了MongoClient连接,fork后的子进程复用这个连接就会触发PyMongo的安全警告。
定位触发位置的方法
你可以在应用入口文件的最开头添加如下代码,将警告转为带完整调用栈的输出,直接定位到哪行代码触发了提前连接:
import warnings import traceback def warn_with_traceback(message, category, filename, lineno, file=None, line=None): traceback.print_stack() warnings._showwarnmsg_impl(message, category, filename, lineno, file, line) warnings.showwarning = warn_with_traceback
重启uWSGI后就能看到完整的调用栈,直接定位触发提前连接的代码行。
修复方案
1. 调整应用初始化顺序
你当前create_app函数中的初始化顺序存在明显问题:Mongo相关配置、DB初始化的调用在创建Flask-Dance蓝图之后。创建Dance蓝图时会实例化你自定义的MongoStorage,若此时触发任何DB访问,就会提前建立连接。
请将初始化顺序调整为:
def create_app(): app = Flask(__name__) app.config.from_object(app_config) # 第一步:先设置所有Mongo相关配置 app.config['MONGO_CONNECT'] = False # 第二步:初始化DB init_db(app) # 第三步:初始化Session Session(app) # 第四步:再创建依赖DB的Flask-Dance蓝图 azure_oauth = misc.create_azure_dance_blueprint(app) google_oauth = misc.create_google_dance_blueprint(app) # 第五步:注册所有蓝图 app.register_blueprint(graph_auth_routes.bp) app.register_blueprint(google_auth_routes.bp) app.register_blueprint(storyboard_routes.bp) return app
2. 禁止在初始化阶段执行DB操作
检查所有全局代码、Flask扩展初始化逻辑,确保没有在请求上下文之外(也就是应用加载阶段)执行任何Mongo读写操作,所有DB调用都要放到路由、请求钩子等请求上下文的逻辑中。
3. 可选方案:直接使用lazy-apps配置
如果不想修改代码,lazy-apps = true 是完全可以在生产环境使用的方案。该配置会让uWSGI在fork完子进程后,每个子进程独立加载应用实例,MongoClient只会在子进程中创建,不会触发警告,除了轻微增加启动时的内存占用外,没有其他明显副作用,绝大多数生产场景都可以正常使用。
内容的提问来源于stack exchange,提问作者Joenarr Bronarsson
相关产品推荐
相关产品推荐

