Когда проверяется/используется Djangos CONN_MAX_AGE?

Недавно у меня возникла проблема "Слишком много соединений" моего приложения Django+Celery с БД Postgres на Heroku.

Может ли проблема заключаться в перезапуске диноскопа? Идея заключается в том, что перезапуск dyno разрывает соединение, но Postgres сохраняет их.

Установка CONN_MAX_AGE, кажется, решила проблему, но я не уверен.

Теперь вопрос заключается в следующем: Как работает CONN_MAX_AGE?

(1) Активно ли Django проверяет возраст соединения и закрывает + перезапускает его, когда оно слишком старое

или

(2) Является ли CONN_MAX_AGE параметром самого соединения, так что postgres автоматически закрывает соединение по истечении этого времени?

Активно ли Django проверяет возраст соединения и закрывает + перезапускает его, если оно слишком старое.

Django будет каждый раз, когда открывает соединение, устанавливать время, когда он должен закрыть соединение [GitHub]:

class BaseDatabaseWrapper:
    # …
    @async_unsafe
    def connect(self):
        # …
        max_age = self.settings_dict["CONN_MAX_AGE"]
        self.close_at = None if max_age is None else time.monotonic() + max_age

Затем, когда будет вызван метод с именем .close_if_unusable_or_obsolete(), Django закроет соединение [GitHub]:

class BaseDatabaseWrapper:
    # …
    def close_if_unusable_or_obsolete(self):
        # …
        if self.connection is not None:
            # …
            if self.close_at is not None and time.monotonic() >= self.close_at:
                self.close()
                return

You can call that method yourself to "recycle" connections. But it is by default done when a request starts and when a request ends, indeed Django registers this on two signals [GitHub]:

def
close_old_connections(**kwargs):
    for conn in connections.all(initialized_only=True):
        conn.close_if_unusable_or_obsolete()


signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)

Таким образом, до выполнения запроса он будет перерабатывать соединения, а после выполнения запроса - перерабатывать соединения с неустранимыми ошибками или устаревшие. Утилизация в середине запроса может быть не очень хорошей идеей, поскольку соединение может быть государственным.

Вернуться на верх