Можете ли вы определить, насколько хорошо клиент справляется с потоком сообщений веб-сокета? - PullRequest
0 голосов
/ 16 апреля 2019

Я пишу сервис потокового видео и думал о потоковом видео через веб-сокеты.

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

Можете ли вы определить, когда торнадо посылает слишком много для клиента, чтобы получить?

1 Ответ

1 голос
/ 16 апреля 2019

Вам не нужно беспокоиться о медленной сети;но вам нужно беспокоиться о быстрой сети.


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

Допустим, вы читаете и отправляете видео частями.Вот как может выглядеть ваш код:

while True:
    self.write(chunk)
    await self.flush() # write chunk to network

Оператор await self.flush() приостановит цикл, пока чанк не будет записан в сеть.Так что если это медленная сеть, она будет дольше задерживаться.Как видите, вам не нужно беспокоиться о том, чтобы опередить клиента.


Однако, если сеть вашего клиента быстрая, операция flush также будет очень быстрой, и этоможет заблокировать ваш сервер, потому что этот цикл будет продолжаться до тех пор, пока все данные не будут отправлены, и IOLoop не получит возможности обслуживать других клиентов.

В этих случаях Бен Дарнелл, сопровождающий торнадо, предложил оченьумное решение в ветке гугл-форумов , которое он называет:

обслуживать каждого клиента со «справедливой» скоростью, вместо того чтобы позволить одному клиенту использовать столько пропускной способности, сколько вы можете датьit.

Вот код (взятый прямо из поста Бена Дарнелла):

while True:
    # Start the clock to ensure a steady maximum rate
    deadline = IOLoop.current().time() + 0.1

    # Read a 1MB chunk
    self.write(chunk)

    await self.flush()

    # This sleep will be instant if the deadline has already passed;
    # otherwise we'll sleep long enough to keep the transfer
    # rate around 10MB/sec (adjust the numbers above as needed
    # for your desired transfer rate)

    await gen.sleep(deadline)

Теперь, даже если операция flush быстрая, в следующем операторе циклбудет спать до крайнего срока, что позволит серверу обслуживать других клиентов.

...