Django:Postgres 连接未关闭

Posted

技术标签:

【中文标题】Django:Postgres 连接未关闭【英文标题】:Django: Postgres connection not closing 【发布时间】:2016-06-09 20:10:21 【问题描述】:

我的 django 应用程序会随着时间的推移累积 postgres 连接。似乎大约每 30 分钟建立一个新连接并且旧连接不会关闭(见屏幕)。 一段时间后,由于最大连接数设置为 100,因此所有连接都被阻止。

有谁知道是什么导致了这个问题?

我在集成了一些 celery tasks 后发现了这一点。所以我很确定它与芹菜有关。

所以我尝试在每个任务之后使用after_return 方法手动关闭连接:

from django.db import connection

class DBTask(Task):
    abstract = True

    def after_return(self, *args, **kwargs):
        connection.close()

@task(name='example', base=DBTask)
def example_task(value):
    # do some stuff

但这也无济于事。 也许我完全错了,它根本与celery 无关。

我的数据库配置:

DATABASES = 
    'default': 
        'ENGINE': 'django.contrib.gis.db.backends.postgis',
        'NAME': 'production', 
        'USER': 'production', 
        'HOST': 'some.host', 
        'CONN_MAX_AGE': 0,
    ,

已安装的包:

django 1.8.9 pyscopg2 2.6.1 芹菜 3.1.20 django-celery 3.1.17

应用部署在webfaction(也许这有帮助)

我也看到了这个question,但设置CONN_MAX_AGE: 0 没有帮助。

更新:

尝试在每个 celery 任务末尾添加connection.close(),但连接数仍在增加。

更新 2:

尝试在 celery 文件的顶部添加 connection.close(),但这也无济于事。

更新 3:

这是我在 celery 任务中实际使用的代码:

celery_tasks.py

@task(name='push_notifications', base=DBTask)
def push_notifications_task(user_id):
    user = CustomUser.objects.get(id=user_id)
    PusherAPI().push_notifications(user)
    connection.close()

models.py

class PusherAPI(object):

    def push_notifications(self, user):
        from .serializers import NotificationSerializer
        self.pusher.trigger(
            'user_%s' % user.slug,
            'notifications',
            NotificationSerializer(user).data
        )

serializers.py

class NotificationSerializer(object):

    def __init__(self, user=None):
        if user is None:
            self.user = get_current_user()
        else:
            self.user = user

    @property
    def data(self):
        # get notifications from db
        notifications = self.user.notifications.unread()
        # create the notification dict
        ...
        return note_dict

唯一的数据库查询位于CustomUser.objects.get(id=user_id)notifications = self.user.notifications.unread()

【问题讨论】:

您的 celery 任务是否使用/创建连接?如果是这样,您是否尝试在 celery 任务中关闭它们,而不是在任务完成后关闭它们? 不,我没试过。你认为这有什么不同吗? 这可能会有所不同,因为在任务中关闭的连接可能与您现在在任务之外关闭的连接不同。但我对芹菜的了解还不够,无法确定这一点。 我会试试的。我会告诉你它是否有效 您确定实际上是旧连接没有关闭,而不是因为应用程序的某些部分无法处理负载而堆积起来的新连接?您是否查看过各个连接,例如SELECT * FROM pg_stat_activity;? 【参考方案1】:

确保实际上没有关闭的是旧连接,而不是因为应用程序的某些部分无法处理负载而堆积起来的新连接。查看各个连接,例如SELECT * FROM pg_stat_activity;

【讨论】:

以上是关于Django:Postgres 连接未关闭的主要内容,如果未能解决你的问题,请参考以下文章

Django 3.0 — 异步测试后数据库连接未关闭

为单个 Django 查询关闭 Postgres 并行查询

Django Admin 搜索查询未命中 Postgres 索引

从 CharField 更改为 IntegerField - Postgres 列数据类型未更改 Django

为 Django Postgres 连接强制 SSL

在 EC2 上运行的 Postgres 服务器每隔一段时间就会关闭。无法在此处隔离问题