Django Postgresql Heroku: Операционная ошибка — «FATAL слишком много соединений для имени пользователя роли»

Я запускаю веб-приложение, используя Django и Django Rest Framework на Heroku с хранилищем данных postgresql и redis. Я нахожусь на бесплатном уровне postgresql, который ограничен 20 подключениями.

Раньше с этим не было проблем, но недавно я начал использовать каналы django 2.0 и сервер daphne (переключил мой Procfile с gunicorn на daphne, например это руководство), и теперь я столкнулся со всевозможными странными проблемами.

Наиболее важным является то, что соединения с базой данных остаются открытыми, поэтому во время работы приложения количество соединений продолжает увеличиваться, пока не достигнет 20, и выдает следующее сообщение об ошибке: Операционная ошибка — «FATAL слишком много соединений для роли «username» '

Описание ошибки Sentry

использование соединения postgresql Затем мне приходится вручную заходить в оболочку и каждый раз набирать heroku pg:killall, это, очевидно, невыполнимое решение, и это производство, поэтому мои пользователи не могут получить доступ к сайту и получить 500 ошибок. Был бы очень признателен за любую помощь.

Я пытался:

Добавление этого к моим разным взглядам в разных местах

from django.db import connections conections.close_all()

for con in connections: con.close()

Я также пытался сделать SELECT * from pg_activity и видел кучу вещей, но понятия не имею, что с этим делать:

Heroku Dataclip pg_activity


person Tomiwa    schedule 06.02.2018    source источник


Ответы (3)


Мы разобрались, в чем проблема. Я предполагаю, что вы используете dj_database_url, как в руководстве по героку. Все, что вам нужно сделать, это удалить conn_max_age.

db_from_env = dj_database_url.config()
person Leonid Ivanov    schedule 17.03.2018

Есть решение:

В настоящее время heroku предоставляет пакет django_heroku, который имеет дело с конфигурацией приложения django-heroku по умолчанию, поэтому, когда вы вызываете django_heroku.config(locals()) в конце вашего settings.py, конфигурация базы данных CONN_MAX_AGE по умолчанию устанавливается на 600 секунды, поэтому значение по умолчанию для django равно 0, что означает все соединения с базой данных закрываются после завершения запроса, если вы не замените значение CONN_MAX_AGE после вызова django_heroku.config(locals()), значение этого поля по умолчанию равно 600, что означает, что соединения с БД все еще активны в течение 600 секунд, вызывая эту проблему.

Поместите эту строку в конец вашего settings.py, она обязательно должна быть после конфигурации heroku:

django_heroku.config(locals())
DATABASES['default']['CONN_MAX_AGE'] = 0
person Marvin Correia    schedule 07.02.2021
comment
Я попробовал ваше решение, но мне все еще нужно подождать 600 секунд по умолчанию, прежде чем запрашивать новое соединение. - person RobZ; 17.02.2021
comment
@RobZ Уверен, что вы вызываете DATABASES['default']['CONN_MAX_AGE'] = 0 в конце вашего settings.py и переустанавливаете свое приложение на heroku. - person Marvin Correia; 18.02.2021
comment
@RobZ Для меня это решение работает нормально! - person Marvin Correia; 18.02.2021
comment
после дополнительных исследований проблема возникла из-за некоторых пользовательских потоков, которые я выполнял в рамках задачи/работника. Соединения внутри потоков сохраняются. Вне потоков DATABASES['default']['CONN_MAX_AGE'] = 0 работало так, как ожидалось, и соединения сразу же прерывались после использования. - person RobZ; 18.02.2021

Я думаю, что, возможно, я решил это.

Одним из изменений, которые я внес, было изменение способа закрытия соединений.

Ключевым моментом является закрытие старых соединений до и после различных функций просмотра.

from django.db import close_old_connections

@csrf_exempt
@api_view(['GET', ])
def search(request):
    close_old_connections()
    # do stuff
    close_old_connections()
person Tomiwa    schedule 01.03.2018
comment
Вы можете использовать такой инструмент, как панель инструментов отладки django, чтобы увидеть, какие представления содержат больше всего SQL-запросов. соединения. Или вы можете попытаться сделать вывод, основываясь на своем понимании того, как работает ваше приложение, какое из представлений имеет наибольшее количество обращений к базе данных. - person Tomiwa; 24.07.2018