Вам не нужно беспокоиться о медленной сети;но вам нужно беспокоиться о быстрой сети.
Вы не сможете записать в сеть больше данных, чем может принять клиент.Таким образом, вы не будете продвигаться вперед.
Допустим, вы читаете и отправляете видео частями.Вот как может выглядеть ваш код:
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
быстрая, в следующем операторе циклбудет спать до крайнего срока, что позволит серверу обслуживать других клиентов.