gevent和postgres:异步连接失败

时间:2013-07-07 17:48:53

标签: python django postgresql gevent

我正在使用gevent来处理基于Django的Web系统上的API I / O.

我用猴子修补了:

import gevent.monkey; gevent.monkey.patch_socket()

我使用以下方法修补了psychopg:

import psycogreen; psycogreen.gevent.patch_psycopg()

尽管如此,某些Django调用因此Model.save()失败并出现错误:“异步连接失败”。我是否需要做其他事情才能在Django环境中制作postgres greenlet-safe?还有其他我想念的东西吗?

1 个答案:

答案 0 :(得分:5)

这个问题上有一个article,不幸的是它是用俄语写的。让我引用最后一部分:

  

所有连接都存储在django.db.connections中   django.db.utils.ConnectionHandler的实例。每次ORM   即将发出查询,它通过调用请求数据库连接   连接[ '缺省'] 。反过来, ConnectionHandler .__ getattr __ 检查是否存在连接   ConnectionHandler._connections,如果是,则创建一个新的   空。

     

使用后应关闭所有打开的连接。有一个信号   request_finished,由...运行   django.http.HttpResponseBase.close。 Django关闭数据库连接   在最后一刻,当没有人可以再使用它 - 而且它   似乎很合理。

     

然而,关于ConnectionHandler如何存储数据库有一些棘手的部分   连接。它使用threading.local,成为   monkeypatching后gevent.local.local。宣布一次,这个   结构就像它在每个greenlet中都是独一无二的一样。调节器   * some_view *在一个greenlet中开始工作,现在我们在* ConnectionHandler._connections *中有一个连接。然后我们创造了一些   更多的greenlets,并得到一个空的   * ConnectionHandlers._connections *,他们从池中获得了connectinos。新的greenlets完成后,他们的本地()的内容消失了,   并且数据库连接与它们一起消失而没有返回池中。在   有些时候,游泳池变空了

     

开发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