WebSocket (сервер python, клиент javascript/rxjs) отсутствующие сообщения

Вступление

Я стараюсь предоставить как можно больше информации заранее, так что если я что-то упустил, пожалуйста, дайте мне знать. Даунвотеры/клоузеры: пожалуйста, объясните мне, чтобы я мог исправить вопрос.

Мотивация: сервер выполняет работу (asyncio с многопроцессорностью), клиент только запрашивает и представляет данные. WebSockets (далее WS) используются в первую очередь для минимизации задержки запросов и ответов (протоколы соединения делаются заранее, а TLS-соединение выполняется один раз). WS использует TCP, который обеспечивает достаточно прозрачные транзакции... нет необходимости в UDP или чем-то еще для большей скорости.

Настройка

  • СерверWS: Каналы Python/Daphne/Django (обновлено)
  • WS клиент: Javascript/Angular/Rxjs (обновлено)
  • Оба запущены на localhost (физическая пропускная способность не ограничена, )

Приложения

  • Клиент: Angular, в основном запрашивает и форматирует данные для представления
  • .
  • Сервер 1: Django channels async JSON consumer (фреймворк asyncio... может быть важен позже).
  • Сервер 2: Python с использованием пакета WebSockets pypi asyncio (в настоящее время устаревший... будет рассмотрен позже... подтверждено, что это не проблема).

Экземпляр сервера 1 соединяется с сервером 2 TLS WS-соединением.

Проблема

Я реализовал серверы несколько лет назад. Короче говоря, при использовании await с Django ORM я столкнулся с некоторыми аспектами задержки в местах, которых я не ожидал. Короткий ответ? Я просто переключил соединения с БД с database_sync_to_async на обертку вызовов в asyncio.to_thread. Параллельность улучшилась в 10 раз, без сомнения, так как я делал много обращений к БД в начале и конце транзакции, отправляя обновления в Javascript-интерфейс. Перемещение этих вызовов из asyncio/await в потоки решило эту проблему.

До этого момента я не замечал никаких аномалий в данных, и мне не приходило в голову, что они могут быть. Теперь я вижу, что пропускная способность всей моей серверной архитектуры надежна и проверена... Я проследил все сообщения через систему и вижу, что строка запросов обрабатывается, создавая наборы данных размером в несколько мегабайт, и отправляет их обратно через последнее соединение WS Rxjs в JS-интерфейс. Я вижу, что все сообщения были «отправлены» асинхронным потребителем каналов Daphne/Django, они выполнены оперативно, и все данные присутствуют.

Однако я заметил, что примерно в 85% случаев JS UI пропускает от 1 до 12 ответов в конце передаваемой последовательности с сервера 1, и они никогда не появляются. Это происходит из примерно 42 соответствующих запросов сообщений, инициированных JS UI и переданных по WS на сервер 1. Все серверы Python ставят данные в очередь соответствующим образом, и, как я уже говорил, я отследил доставку каждого сообщения, насколько это возможно, прежде чем они исчезнут после отправки сервером 1.

Решения

Пока что ничего. Возврат кода в «медленное» состояние с использованием транзакций базы данных async/await явно замедляет работу и, похоже, решает проблему. Мне кажется очевидным, что это как-то связано с очередями и буферизацией в WS-соединении между сервером 1 и JS UI. Серия (10-15) маленьких (кБ) и больших (МБ) сообщений, отправленных за период около 1,5 секунд, кажется, вызывает наибольшие проблемы. Однако это непоследовательно: разные сообщения пропадают, а иногда все сообщения принимаются. Я проверяю, просто обновляя страницу (новая сессия браузера, новое WS-соединение, новые рабочие процессы на сервере и т. д.), и наблюдаю разное поведение.

Я пытаюсь немного приблизиться к TCP-уровню сервера 1 WS, чтобы убедиться, что пакеты действительно обрабатываются на TCP-уровне... Я не закончил эту проверку. Мне нужно выяснить, как посмотреть TCP-сессии на JS UI в браузере.

Другие попытки

Я подумал, что, возможно, мой обработчик Rxjs WS в браузере слишком долго обрабатывает сообщения, поэтому я попробовал добавить «буфер» с помощью Rxjs Subject, который позволил бы моему обработчику WS передавать его на обработку парсинга/форматирования, просто next записывая данные в observable и подписываясь на это в другом месте в службе WS, но это, похоже, не сработало. Мне нужно попробовать очередь отправки с задержкой на сервере 1 приложения в качестве первой попытки с использованием asyncio.sleep, чтобы посмотреть, улучшит ли искусственное замедление ситуацию.

Идеи

Кто-нибудь знает, как копнуть чуть дальше в функции Rxjs WebSocket, чтобы узнать, заполняются ли буферы и отбрасываются ли сообщения? TCP должен обеспечивать доставку сообщения, поэтому мне кажется, что проблема на стороне браузера. Я использую браузер, потому что я хочу для своего приложения, так что это не исчезнет.

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