【问题标题】:Best practices for persistent database connections in Python when using Flask使用 Flask 时 Python 中持久数据库连接的最佳实践
【发布时间】:2019-08-26 15:27:13
【问题描述】:

我的问题是关于在生产环境或其他关注性能的环境中使用 Flask 时处理数据库连接的推荐方法。在 Flask 中,g 对象可用于存储事物,并且可以将打开的数据库连接放置在那里,以允许应用程序在同一请求期间在后续数据库查询中重用它们。但是,g 对象不会在请求之间持续存在,因此似乎每个新请求都需要一个新的数据库连接(以及由此带来的性能损失)。

我在这件事上发现的最相关的问题是这个:How to preserve database connection in a python web server 但答案只提出了连接池的抽象概念(没有将它与如何在 Flask 中使用它以及它如何在请求中生存下来联系起来)或提出仅与一种特定类型的数据库或特定堆栈相关的解决方案。

所以我的问题是关于在生产基于 Flask 并连接到任何类型数据库的应用程序时应该采取的一般方法。似乎涉及连接池的事情正朝着正确的方向发展,尤其是因为这适用于传统的 Python 应用程序。但我想知道在使用 Flask 时推荐的方法是什么,因为前面提到的跨连接持久性问题,以及生产中的 Flask 应用程序是从 WSGI 服务器运行的事实,这可能会增加进一步的复杂性。

编辑:基于 cmets 推荐烧瓶 sqlalchemy。假设烧瓶 sqlalchemy 解决了这个问题,它是否也适用于 Neo4J 或 Flask 应用程序使用的任何任意数据库?许多现有的数据库连接器已经原生支持池化,那么为什么要引入一个额外的依赖项,其主要目的是提供 ORM 功能而不是连接管理?此外,sqlalchemy 如何解决跨请求持久性的基本问题?

【问题讨论】:

标签: python database flask database-connection pooling


【解决方案1】:

事实证明,有一种简单的方法可以实现我所追求的目标。但正如评论者所建议的那样,如果有可能走烧瓶 sqlalchemy 路线,那么您可能想走那条路。我解决问题的方法是将连接对象保存在模块级变量中,然后根据需要导入该变量。这样它就可以在 Flask 和其他模块中使用。这是我所做的简化版本:

app.py

from flask import Flask
from extensions import neo4j

app = Flask(__name__)
neo4j.init_app(app)

extensions.py

from neo4j_db import Neo4j

neo4j = Neo4j()

neo4j_db.py

from neo4j import GraphDatabase

class Neo4j:
    def __init__(self):
        self.app = None
        self.driver = None

    def init_app(self, app):
        self.app = app
        self.connect()

    def connect(self):
        self.driver = GraphDatabase.driver('bolt://xxx')
        return self.driver

    def get_db(self):
        if not self.driver:
            return self.connect()
        return self.driver

example.py

from extensions import neo4j

driver = neo4j.get_db()

从这里 driver 将包含将在 Flask 请求中持续存在的数据库驱动程序。

希望对遇到同样问题的人有所帮助。

【讨论】:

  • 此解决方案有效,我已在 MongoDB 中尝试过。有人愿意详细说明它为什么起作用吗?据我了解from extensions import neo4j 将运行整个模块extension.py 再次重新初始化neo4j 变量。
  • 在 Python 中,“出于效率原因,每个模块在每个解释器会话中只导入一次”,如此处docs.python.org/3/tutorial/modules.html 因此,当 Flask 应用程序启动并从那时起保留在内存中时,相关加载会发生一次.
  • 我正在使用 postgres,我基本上是在烧瓶应用程序启动期间在 app.py 中启动 psycopg2 连接。到目前为止还没有遇到问题,并且在多个请求(AFAIK)中只维护了 1 个连接。有这种解决方案的cmets吗?和你的一样吗?
  • 您的方法也应该有效。但是,随着您的应用程序的增长(例如,使用更多类型的数据库连接),您可能需要考虑这里给出的模式,将其分解为多个文件,以使您的应用程序更加结构化和模块化。
  • @ospider 你可以简单地使用一个为你管理连接的库。例如,您可以使用 sqlalchemy.pool 中的 QueuePool 类。
猜你喜欢
  • 1970-01-01
  • 2016-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 2020-05-05
  • 2018-08-23
  • 2010-11-06
相关资源
最近更新 更多