Является ли мультиплексирование соединений через веб-сокеты важной оптимизацией в Django Channels ›= 2?

Я поддерживаю приложение Django Channels v1 с шестью потребителями, мультиплексированными через одно соединение WebSocket. Я обновляюсь до Django Channels v2, где (де) мультиплексирование соединений больше не поддерживается; см. Проблема GitHub № 825 - (Повторная) реализация мультиплексирования . Если я хочу мультиплексировать, я могу использовать демультиплексор каналов, channelsmultiplexer, или напишите свой. Я склоняюсь к повторной реализации мультиплексирования, потому что я думаю, что это повлечет за собой меньшее изменение нашего существующего кода.

Перед тем, как сделать это, я провожу некоторую проверку, чтобы выяснить, является ли мультиплексирование даже важной оптимизацией.

Учитывая приложение Django 2 + Channels 2 с поддержкой Redis в среде с балансировкой нагрузки за Nginx с Daphne (в настоящее время планируется в основном SyncConsumers) и Gunicorn, я думаю, что увеличение количества подключений к веб-сокетам в 3–5 раз лишь незначительно увеличит ОЗУ Redis, ОЗУ сервера приложений и ЦП Дафны, а также незначительно увеличит ОЗУ браузера. и ЦП, но это только обоснованное предположение.

  1. Как мне думать о стоимости каждого дополнительного подключения к WebSocket а.) В каналах Django v2 и б.) В браузере?
  2. Я не видел веб-приложений, которые были разработаны для использования множества соединений WebSocket на одной странице. У тебя? Если да, то насколько эффективно? Сколько подключений он использовал?
  3. Что бы вы сделали?

Сообщения Stack Overflow, в которых рассматриваются смежные, но разные вопросы:

  1. Как использовать несколько подключений к веб-сокетам с помощью каналов Django?
  2. Каналы Django 2, реализующие мультиплексор / демультиплексор, такие как каналы 1
  3. Повторное использование существующего веб-сокета в каналах Django

person Myer    schedule 16.04.2021    source источник


Ответы (1)


Как автор channelsmultiplexer я надеюсь, что у меня есть некоторые полезные идеи.

При использовании Channelv2 необходимо помнить одну ключевую вещь: у каждого экземпляра-потребителя есть одна группа выполнения, поэтому, пока он обрабатывает сообщение, он не сможет обработать другое (они попадают в очередь). В частности, если у вас есть действия с вашим потребителем, которые требуют времени (db или другое), потребитель не будет получать других сообщений, пока он выполняет работу. При использовании channelsmultiplexer блокировка не влияет на другие мультиплексированные экземпляры потребителей. Если есть изменения / дополнения, вам нужно channelsmultiplexer не стесняйтесь создавать проблемы в репозитории, я рад внести необходимые изменения, чтобы они соответствовали сценариям использования большего числа людей.

Как мне думать о стоимости каждого дополнительного подключения к веб-сокету а.) В каналах Django v2 и б.) В браузере?

Да, поскольку если ваше туннелирование ws через HTTP2 (не то, что каналы поддерживают, но nginx может помочь вам год, если вы уверены, что все ваши клиенты - http2), браузер пользователей, скорее всего, ограничит количество одновременных HTTP-соединений, которые вы можете открыть. Многие браузеры ограничивают вас примерно 7 открытыми соединениями, но это может измениться в любое время, а мобильный браузер может быть более строгим (как правило, так)

person Matthaus Woolard    schedule 17.04.2021
comment
Если у меня есть несколько экземпляров daphne за балансировщиком нагрузки, действительно ли в Channels v2 будет так, чтобы каждый пользователь был ограничен одной синхронной операцией? Если да, не могли бы вы указать мне место в коде или документации, где это делается? - person Myer; 18.04.2021
comment
не каждое соединение, а каждый потребитель. (так что если вы не используете мультиплексор, что означает каждое соединение "да") github.com/django/channels/blob/main/channels/consumer.py#L58 это await_many_dispatch github.com/django/channels/blob/ на L40, вы можете видеть, что он использовал один и тот же цикл для всех вызываемых. - person Matthaus Woolard; 18.04.2021
comment
это не совсем синхронная операция, они по-прежнему асинхронны (не блокируют другой экземпляр потребителя), но блокируют другие сообщения для этого потребителя. Причина этого в том, что теперь вы можете сохранять состояние в экземпляре-потребителе (это обычный класс), поэтому одновременное выполнение нескольких вещей, считывающих / записывающих это состояние, не является хорошей идеей. - person Matthaus Woolard; 18.04.2021
comment
Спасибо за всю эту информацию; это очень полезно, хотя мне сложно использовать правильную терминологию в каналах v2. 1. run-roop это Скуби-Ду для run-loop, верно;)? 2. Вы упоминаете, что для каждого экземпляра-потребителя существует один цикл выполнения - он охватывает одно конкретное соединение, например один пользователь, да? 3. channelsmultiplexer использует подкласс AsyncJsonWebsocketConsumer. Моим потребителям нужно использовать Django ORM, и в документации по каналам v2 предлагается SyncConsumer в этом случае. Могу ли я использовать channelsmultiplexer с SyncConsumers? - person Myer; 19.04.2021
comment
1) да, извините (должен написать эти вещи на моем телефоне) 2) вы можете, SyncConsumer в основном и потребитель Async, все методы жизни были обернуты для синхронизации. Мультиплексор будет Async, но восходящие потребители могут быть любым потребителем веб-сокета JSON. - person Matthaus Woolard; 19.04.2021