我正在创建一个Flask应用程序,最初使用Flask-SQLAlchemy作为我的数据库连接进行初始开发。首先,我使用一个数据库进行所有开发。然而,一旦应用程序投入生产,我将使用多个数据库-客户可以注册服务,启动他们的数据库,然后使用Flask应用程序访问他们特定的数据库,关闭cname。
我知道Flask-SQLAlchemy可以自己处理会话的打开和关闭,但是由于无法使用Session.configure(bind=engine)
重新配置数据库连接,这并不能满足我的需要(这一段是为了给予了解为什么我不使用Flask-SQLAlchemy,尽管它内置了会话管理)。
我让POC工作了--我设置了一个dbConn
蓝图,在那里处理连接,我设置了一个@dbConn.before_app_request
处理程序,从请求中获取cname,创建一个引擎,并使用新的引擎启动scoped_session,这样就成功地连接到了新的数据库,并获得了用户的特定信息:
Base = declarative_base()
Session = scoped_session(sessionmaker())
def init_db(url):
engine = create_engine(url)
Session.configure(bind=engine)
Base.metadata.create_all(bind=engine)
@dbConn.before_app_request
def set_database():
cname = request.headers['X-Subdomain']
db_url = 'postgresql://tracer_connect:postgrespw@db:5432/'+cname
init_db(db_url)
@dbConn.after_app_request
def close_db_connect(resp):
Session.remove()
return resp
我的大问题是关闭/删除会话。根据SQLAlchemy文档:
确保scoped_session.remove()在Web请求结束时被调用,通常通过与Web框架的事件系统集成来建立一个“on request end”事件。
理论上,在我的块中,应该删除会话,但是当我打开PGAdmin并查看活动的服务器连接时,我看到由请求启动的所有新服务器会话仍然处于活动状态。
我还尝试了end事件的变体,使用了.teardown_request
和.teardown_appcontext
等flask事件,但没有效果。
如果有区别的话,这些请求目前都是只读请求。我很困惑。从我所读到的关于这个问题的所有内容来看,这 * 应该 * 是解决方案,但似乎不是。我对Flask和SQLAlchemy还是个新手,所以我很乐意接受任何人的指导。我也愿意接受这可能是一个postgres或PGAdmin问题。理论上,也许sqlalchemy会话正在被删除,但是服务器progress会话仍然存在,但是我已经没有什么技术来尝试测试这些理论了。
1条答案
按热度按时间f4t66c6m1#
SQLAlchemy使用一个连接池,这样连接就可以在请求之间重用。从性能的Angular 来看,创建一个新的连接是非常昂贵的。也许您看到的活动连接只是在池中。我将首先设置NullPool,看看连接是否正在关闭,然后删除它,设置echo_pool标志,看看连接是否返回到池中,下面将对此进行解释。
我认为这里解释了一个允许溢出的集合大小:连接池配置
下一节还将解释如何使用NullPool,我认为它只是打开和关闭一个连接(对性能不好,但可能易于调试):交换池实现
池文档还解释了如何打开池的调试。然后,您可以查看连接是否返回到池。
https://docs.sqlalchemy.org/en/20/core/pooling.html#logging-reset-on-return-events