Каналы Django: Ошибка UNKNOWN при записи в сокет. Соединение потеряно
У нас есть Django Channels в связке с uvicorn и azure redis instance. Наш часовой заваливается ошибками, такими как:
Exception in ASGI application
ssd.consumers in disconnect
Error UNKNOWN while writing to socket. Connection lost.
Исключение возникает в файле asyncio/streams.py, как показано на примере
Моя главная проблема заключается в том, что я не знаю, разрывает ли Redis это соединение, или сервер не хочет его поддерживать? Любые подсказки приветствуются. Я не наблюдал такого поведения на локальном экземпляре Redis. Мы работаем на следующих пакетах:
Django = "~4.2"
redis = "^4.3.1"
channels = {extras = ["daphne"], version = "^4.0.0"}
channels-redis = "^4.1.0"
uvicorn = {extras = ["standard"], version = "^0.24.0.post1"}
Стоит отметить, что в большинстве случаев он работает, вебсокеты функционируют, иногда он просто случайно выбрасывает исключение, упомянутое выше.
redis
использует пакет asyncio
для установления соединения через websocket и создания асинхронного конвейера данных между клиентом и сервером. Сервер использует различные функции из пакета asyncio
для связи с клиентом, и большинство из них работают нормально. Однако если вы проверите PyPi на channels-redis
, то увидите, что эта библиотека не проходит тесты и является нестабильной.
Однако вы должны быть в состоянии обеспечить его стабильную работу. Убедитесь, что вы используете Python 3.8+, который требуется для redis
, как показано на странице PyPi. Как я уже объяснял, channels-redis
может быть нестабильным в некоторых отношениях, но я думаю, что в основном это нестабильность в поиске правильной серии пакетов, которые полностью совместимы и вызывают правильные имена функций, поскольку они, похоже, меняются в библиотеках. Я рекомендую использовать что-то новое, но не слишком старое, с хорошей поддержкой библиотек, прямо сейчас я предлагаю Python 3.11.8.
Когда вы устанавливаете/обновляете пакеты с помощью pip, вы должны устанавливать их в том порядке, в котором требуют зависимости, и они должны устанавливать версию пакета, совместимую с другими пакетами. Именно здесь вы можете захотеть проверить стабильность каждой версии и откатиться channels-redis
назад, чтобы посмотреть, не изменилось ли что-нибудь, сверяясь с redis
версией и датой выпуска на PyPi.
При установке последней версии Django for Python 3.11.8 следует установить redis
и channels-redis
, и более чем вероятно, что все будет работать. Но, возможно, стоит обратить внимание на текущие версии пакетов или вообще использовать тестовый сервер, если вы работаете в продакшене.
pip install Django --upgrade
pip install redis --upgrade
pip install channels-redis --upgrade
Очевидно, в либе channels_redis
можно указать больше конфигураций, которые не указаны в документации. Поскольку Azure Cache For Redis не является либеральным, он тайминговал неработающие соединения. Изменение моих настроек на эти решило проблему:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [
{ # specifying host as dict with additional keys for redis-py client was a key to solve it.
"address": CHANNELS_REDIS_URL,
"retry_on_timeout": True,
"health_check_interval": 1,
"socket_keepalive": True,
}
],
"capacity": 1500,
"expiry": 5,
},
},
}