Django периодически и временно не может подключиться к базе данных. Это приводит к временному таймауту и сбою запросов к ней.
Установка: AWS RDS db (postgres), Dockerised django backend, размещенный на elastic beanstalk
Некоторый контекст:
У меня есть django backend, который принимает запросы на отправку формы с отдельного сайта, и django сохраняет данные формы в базу данных. Приложение django, которое я создаю, заменяет существующее программное обеспечение, которое используется для этой цели. Я начал тестировать приложение django, заставляя сайт отправлять данные формы как существующему программному обеспечению, так и моему приложению django. Я заметил, что иногда мое приложение django не получает форму, которую получает существующее программное обеспечение. Например, django закончит день с 25 формами, а существующее ПО - с 26. У меня настроено логирование запросов, но даже в логах не видно записей о 26-й форме.
Чтобы отладить, что происходит не так, я настроил команду скрипта в приложении django на отправку форм на конечную точку моего приложения django каждую минуту. В конце концов, это не удалось:
Exception retrieving data fields
SSL SYSCALL error: EOF detected
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.OperationalError: SSL SYSCALL error: EOF detected
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/code/src/leads/management/commands/bug_finder.py", line 115, in handle
data_field = DataField.objects.get(api_field=field)
File "/usr/local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 431, in get
num = len(clone)
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 262, in __len__
self._fetch_all()
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 1324, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 51, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 98, in execute
return super().execute(sql, params)
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
django.db.utils.OperationalError: SSL SYSCALL error: EOF detected
[DJANGO] DEBUG 2022-09-08 22:43:09,567 connectionpool urllib3.connectionpool._new_conn:1003: Starting new HTTPS connection (1): url:443
[DJANGO] DEBUG 2022-09-08 22:43:09,730 connectionpool urllib3.connectionpool._make_request:456: https://url:443 "POST /new_lead/5kbLWVNXHQ3U6lJ9trME8hPSf HTTP/1.1" 400 799
Похоже, что django иногда не может соединиться с базой данных для выполнения запросов/сохранений.
Исключение моего локального скрипта возникло при попытке получить доступ к моделям полей данных из базы данных, чтобы сгенерировать поддельную полезную нагрузку для формы:
payload = {}
for field in api_fields:
try:
data_field = DataField.objects.get(api_field=field)
payload[field] = generate_value(data_field)
except DataField.DoesNotExist:
continue
Полагаю, что иногда при запросах с сайта django не может соединиться с базой данных, возникает исключение, форма не сохраняется и не удается отправить ответ на сайт.
При поиске вышеупомянутого исключения, большинство ответов, кажется, предполагают, что это связано с настройками постоянного соединения с БД, которые имеют неправильные настройки таймаута, что я не думаю, что это связано с системой ответа на запрос django.
Нормально ли это, связано ли это с падением AWS? Есть ли решение обернуть представление конечной точки в try catch для этого исключения и попытаться сохранить данные формы в кэше, пока django не сможет снова соединиться с БД? Есть ли простой способ проверить, подключен ли django к БД?
Что-то вроде обертки, которая эффективно делает:
try:
view_function()
except psycopg2.OperationalError:
counter = 0
while counter <= 3:
if django.is_connected_to_db:
return view_function()
else:
counter += 1
time.sleep(20)
save_request_to_cache_to_try_later
return response
Кажется, что я не должен этого делать
Для вашего вопроса относительно проверки соединения с базой данных в Django, вы можете использовать этот код там, где захотите:
from django.db import connections
from django.db.utils import OperationalError
try:
db_conn = connections['default']
except OperationalError:
time.sleep(20)
По поводу проблемы с базой данных: Какой именно регион вы используете на AWS? Я развернул несколько проектов на us-east-1 и eu-central-1 и не имел этой проблемы.
Эта проблема кажется необычной, и вам следует отправить тикет в службу поддержки AWS по этому поводу. В любом случае, вы можете попробовать перевести ваш RDS на управляемую базу данных Atlastic Beanstalk . По сути, это то же самое, что и обычный RDS, но сетевая конфигурация проще. Просто убедитесь, что RDS находится в том же VPC, что и ваши экземпляры.