Каналы 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, как показано на примере Snippet that throws exception.

Моя главная проблема заключается в том, что я не знаю, разрывает ли 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,
            },
        },
    }
Вернуться на верх