Пользователи ошибочно получают CancelledError при использовании Django ASGI

Наши пользователи ошибочно получают CancelledError для любой страницы в нашей системе. Единственная закономерность, которую мы заметили, заключается в том, что это происходит чаще на страницах, которые требуют больше времени для загрузки во время нормальной работы. Но это абсолютно не ограничивается такими страницами, это может произойти в любом месте нашей системы, например, на странице входа в систему. Все затронутые страницы не используют никакого асинхронного кода или каналов, это стандартные представления django, работающие в модели запрос/ответ (мы перешли на ASGI совсем недавно, и у нас есть только одна страница, использующая каналы, и она работает просто отлично). Мы не можем воспроизвести это последовательно.

Что мы видим в sentry.io:

CancelledError: null
  File "channels/http.py", line 198, in __call__
    await self.handle(scope, async_to_sync(send), body_stream)
  File "asgiref/sync.py", line 435, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "asyncio/tasks.py", line 414, in wait_for
    return await fut

Locally и в журналах Daphne это выглядит так:

2022-10-12 20:00:00,000 WARNING Application instance <Task pending coro=<ProtocolTypeRouter.__call__() running at /home/deploy/.virtualenvs/…/lib/python3.7/site-packages/channels/routing.py:71> wait_for=<Future pending cb=[_chain_future.._call_check_cancel() at /usr/lib/python3.7/asyncio/futures.py:348, <Task WakeupMethWrapper object at 0x7f1adcbf9610>()]>> for connection <WebRequest at 0x7f1adcc6bb50 method=POST uri=/dajaxice/operations.views.calculate_cost_view/ clientproto=HTTP/1.0> took too long to shut down and was killed. 2022-10-12 20:00:00,000 WARNING Application timed out while sending response

С точки зрения пользователя, страница просто не загружается, и ему приходится повторно нажимать на кнопку или обновлять страницу.

Библиотеки, которые мы используем:

python = 3.7
Django = 2.2.12
channels = 3.0.5
channel-redis = 3.4.1

На сервере мы используем: Nginx, supervisor, Daphne.

Для всех запросов (HTTP и websockets) мы используем ASGI.

Наша команда для запуска daphne: daphne -t 300 project.asgi:application

То, что мы уже пытались сделать:

  1. Добавление таймаута в Daphne (как вы можете видеть выше)
  2. Обновление библиотеки channels с 3.0.4 на 3.0.5 (потому что мы нашли информацию о том, что asgiref 3. 3.1, который используется в channels 3.0.4, может быть виновником этой проблемы: https://lightrun.com/answers/django-channels-warning---server---application-instance-took-too-long-to-shut-down-and-was-killed)

Есть идеи, чем это вызвано или как устранить неполадки?

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

В то время причина заключалась в том, что сервер базы данных не имел достаточного ресурса. Мы использовали AWS RDS (MySQL), и использование процессора превышало 99% всякий раз, когда мы получали ошибку.

Используя AWS CloudWatch, вы можете проверить историю использования процессора (CPU Utilization). (Хотя есть много других значений, за которыми нужно следить, но CPU Utilization Rate был единственным проблемным значением)

enter image description here

После обновления типа экземпляра БД проблемы сразу же исчезли.

Читайте больше здесь о AWS CloudWatch для RDS.

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