ado*_*lis 5 python django postgresql gevent
我正在使用gevent来处理基于Django的Web系统上的API I/O.
我用猴子修补了:
import gevent.monkey; gevent.monkey.patch_socket()
Run Code Online (Sandbox Code Playgroud)
我使用以下方法修补了psychopg:
import psycogreen; psycogreen.gevent.patch_psycopg()
Run Code Online (Sandbox Code Playgroud)
尽管如此,某些Django调用因此Model.save()失败并出现错误:"异步连接失败".我是否需要做其他事情才能在Django环境中制作postgres greenlet-safe?还有什么我想念的吗?
有一篇关于这个问题的文章,不幸的是它是用俄语写的.让我引用最后一部分:
所有连接都存储在django.db.connections中,这是django.db.utils.ConnectionHandler的实例.每次ORM即将发出查询时,它都会通过调用连接['default']来请求数据库连接 .反过来,ConnectionHandler .__ getattr__检查ConnectionHandler._connections中是否存在 连接,如果它为空则创建一个新连接.
所有打开的连接应在使用后关闭.有一个信号 request_finished,由django.http.HttpResponseBase.close运行 .Django在最后一刻关闭数据库连接,当时没有人可以再使用它 - 这似乎是合理的.
然而,关于ConnectionHandler如何存储数据库连接存在棘手的部分.它使用threading.local,在monkeypatching之后变成 gevent.local.local.声明一次,这个结构就像它在每个greenlet中都是唯一的一样.Controller*some_view*在一个greenlet中开始工作,现在我们在*ConnectionHandler._connections*中有一个连接.然后我们创建了更多的greenlets,它们得到一个空的*ConnectionHandlers._connections*,并且他们从池中获得了connectinos.在完成新的greenlet之后,他们的local()的内容消失了,并且数据库连接也没有返回池中.在某个时刻,游泳池变空了
开发Django + gevent你应该始终牢记这一点并通过调用django.db.close_connection来关闭数据库连接.它应该在异常时调用,你可以使用装饰器,如:
class autoclose(object):
def __init__(self, f=None):
self.f = f
def __call__(self, *args, **kwargs):
with self:
return self.f(*args, **kwargs)
def __enter__(self):
pass
def __exit__(self, exc_type, exc_info, tb):
from django.db import close_connection
close_connection()
return exc_type is None
Run Code Online (Sandbox Code Playgroud)