无效交易在请求之间持续存在

无效交易在请求之间持续存在,第1张

无效交易在请求之间持续存在

编辑2016-06-05:

解决此问题的PR已于2016年5月26日合并。

烧瓶PR 1822

编辑2015-04-13:

谜团已揭开!

TL; DR:请 务必 使用2014-12-11编辑中的拆解包装配方, 确保 拆解功能成功!

我还使用Flask开始了一项新工作,在我准备好拆包食谱之前,这个问题再次d出。因此,我重新审视了这个问题,并最终弄清了发生了什么。

正如我认为的那样,每当新请求下线时,Flask都会将新的请求上下文推送到请求上下文堆栈中。这用于支持请求本地全局变量,例如会话。

Flask还具有与请求上下文分离的“应用程序”上下文概念。它旨在支持未发生HTTP的测试和CLI访问等功能。我知道这一点,而且我也知道那是Flask-
SQLA放置其数据库会话的地方。

在正常 *** 作期间,请求和应用程序上下文都在请求开始时被推送,并在结束时d出。

但是,事实证明,当推送请求上下文时,请求上下文会检查是否存在现有的应用程序上下文,如果存在,则 不会 推送新的应用程序上下文!

因此,如果由于拆解功能的提高而在请求结束时 d出应用程序上下文,则它不仅会永远存在,甚至不会在其之上推送新的应用程序上下文。

这也解释了我在集成测试中没有理解的一些魔术。您可以插入一些测试数据,然后运行一些请求,即使您不提交,这些请求也将能够访问该数据。这是唯一可行的,因为该请求具有新的请求上下文,但正在重用测试应用程序上下文,因此,它正在重用现有的数据库连接。因此,这确实是一个功能,而不是错误。

就是说,这确实意味着您必须绝对确保您的拆卸功能成功,使用下面的拆卸功能包装器之类的东西。即使没有该功能,这也是一个好主意,以避免泄漏内存和数据库连接,但鉴于这些发现,这一点尤其重要。因此,我将向Flask的文档提交PR。(在这里)

编辑2014-12-11:

我们最后放置的一件事是下面的代码(在我们的应用程序工厂中),该代码包装了所有拆卸函数以确保其记录异常并且不会进一步引发。这样可以确保始终成功d出应用上下文。显然,这必须
您确定所有拆卸功能都已注册之后进行。

# Flask specifies that teardown functions should not raise.# However, they might not have their own error handling,# so we wrap them here to log any errors and prevent errors from# propagating.def wrap_teardown_func(teardown_func):    @wraps(teardown_func)    def log_teardown_error(*args, **kwargs):        try: teardown_func(*args, **kwargs)        except Exception as exc: app.logger.exception(exc)    return log_teardown_errorif app.teardown_request_funcs:    for bp, func_list in app.teardown_request_funcs.items():        for i, func in enumerate(func_list): app.teardown_request_funcs[bp][i] = wrap_teardown_func(func)if app.teardown_appcontext_funcs:    for i, func in enumerate(app.teardown_appcontext_funcs):        app.teardown_appcontext_funcs[i] = wrap_teardown_func(func)

编辑2014-09-19:

好的,结果

--reload-on-exception
不是一个好主意,如果1.)您正在使用多个线程,并且2.)在请求中终止线程可能导致麻烦。我以为uWSGI会等待该工作程序的所有请求完成,就像uWSGI的“优美的重载”功能一样,但事实并非如此。我们开始遇到这样的问题:线程将在Memcached中获取狗锁,然后由于不同线程中的异常而在uWSGI重载worker时终止该线程,这意味着该锁永远不会释放。

移除已

SQLALCHEMY_COMMIT_ON_TEARDOWN
解决问题的一部分,尽管在期间的应用拆卸 期间
我们仍然会偶尔出现错误
session.remove()
。看来这些是由SQLAlchemy问题3043引起的,该问题已在0.9.5版中修复,因此希望升级到0.9.5将使我们能够依赖始终可用的应用程序上下文拆除。

原版的:

首先如何实现仍然是一个悬而未决的问题,但是我确实找到了一种防止这种情况的方式:uWSGI的

--reload-on-exception
选择。

我们的Flask应用程序的错误处理应该捕获几乎所有内容,因此它可以提供自定义错误响应,这意味着只有最意外的异常才应将其处理到uWSGI。因此,无论何时重新加载整个应用程序都是有意义的。

我们还将关闭

SQLALCHEMY_COMMIT_ON_TEARDOWN
,尽管我们可能会显式提交而不是编写自己的回调来删除应用程序,因为我们很少写入数据库。



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5618072.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存