我正在使用带有 SQLAlchemy 和 uWSGI 服务器的 Flask 应用程序。 uWSGI 在 fork 期间通过所有进程重复连接是一个已知问题。有关如何解决此问题的信息在网络上有点分散,但两个主要选项似乎是:
lazy-apps = true
在 uWSGI 的配置中(不推荐,因为它会消耗大量内存)@postfork
装饰器在 fork 后关闭连接,为每个新进程启动新的新连接,但我不清楚何时以及如何在 Flask 应用程序中使用。 这是我的应用程序的示例:
# file: my_app/app.py
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config.from_pyfile(f'../config/settings.py')
db.init_app(app)
db.create_all(app=app)
return app
的样本运行.py 文件:
# file: run.py
from my_app/app import create_app
app = create_app()
if "__main__" == __name__:
app.run(debug=app.config["DEBUG"], port=5000)
所以问题是 postfork 应该在哪里以及如何执行以正确设置 uWSGI 的服务器以在每个进程上使用隔离连接而不使用
lazy-apps = true
?
最佳答案
SQLAlchemy 手册提供了两个例子来解决这个问题:Using Connection Pools with Multiprocessing .
第一种方法涉及 Engine.dispose()
可以使用 uwsgidecorators.postfork
联系正如 Hett 所建议的 - 如果只涉及默认绑定(bind),则应该工作的简单示例:
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "postgres:///test"
db.init_app(app)
def _dispose_db_pool():
with app.app_context():
db.engine.dispose()
try:
from uwsgidecorators import postfork
postfork(_dispose_db_pool)
except ImportError:
# Implement fallback when running outside of uwsgi...
raise
return app
第二个涉及
sqlalchemy.event
并丢弃来自不同 PID 的连接 - 引用:The next approach is to instrument the Pool itself with events so that connections are automatically invalidated in the subprocess. This is a little more magical but probably more foolproof.
如果您想要后一种神奇的解决方案,请参阅文档。
关于flask - 如何正确设置 Flask + uWSGI + SQLAlchemy 以避免数据库连接问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59248806/