Как осуществляется пошаговое управление потоком HTTP/2?

Как сказано в spec:

Управление потоком специфично для соединения. Оба типа управления потоком осуществляются между конечными точками одного прыжка, а не на всем сквозном пути.

А в 6.9 WINDOW_UPDATE

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

Но как это вообще возможно? Кажется, это требует, чтобы все посредники понимали протокол h2 или h2c, и у меня есть два вопроса:

  1. HTTP/2 — относительно новый стандарт, и я видел, что он включен на многих веб-сайтах (включая мой блог). Хотя я могу посещать эти веб-сайты без каких-либо проблем, означает ли это, что каждое промежуточное устройство на этом пути, такое как маршрутизаторы, концентраторы и т. д., уже внедрило свой собственный стек HTTP/2 и алгоритмы управления потоком (поскольку RFC7540 не предусматривает алгоритм управления потоком)?

  2. Большинство веб-сайтов используют h2, а не h2c, который шифрует данные прикладного уровня. Управление потоком HTTP/2 осуществляется приемниками, отправляющими кадр WINDOW_UPDATE, который также является данными прикладного уровня, тогда как промежуточные устройства узнают, что это за данные? Если они не могут расшифровать данные и увидеть часть Window Size Increment, как они могут управлять потоком, не пересылая кадр WINDOW_UPDATE?

введите здесь описание изображения


person laike9m    schedule 22.11.2016    source источник


Ответы (2)


Сначала несколько поправок.

Маркер h2c относится к открытому тексту HTTP/2 (отсюда c в h2c). Во втором пункте вы говорите, что большинство веб-сайтов используют его, но на самом деле очень немногие, потому что браузеры его не реализуют. Подавляющее большинство веб-сайтов используют h2.

Токен h2 относится к зашифрованному h2c или, что то же самое, h2c через TLS.

Когда клиент и сервер договариваются о том, чтобы говорить h2, байты, отправляемые клиентом, шифруются и передаются в зашифрованном виде на всем пути к серверу. Это означает, что у посредников нет возможности расшифровать трафик (спасибо).

В этом случае «переход», на который ссылается спецификация HTTP/2, — это весь сегмент сети между клиентом и сервером.

Спецификация HTTP/2, однако, должна быть общей и не беспокоиться о том, как браузеры и веб-серверы взаимодействуют при определении проводного протокола, такого как HTTP/2.

Представьте себе ситуацию, когда клиент выполняет запрос HTTP/2 к server1, используя h2, а server1 нужно вызвать server2 для выполнения запроса, на этот раз используя h2c. Например, server1 может быть внешним «прокси», который перенаправляет запросы на «правильный» внутренний сервер в зависимости от некоторой логики.

В этом случае у вас есть 2 перехода: клиент-сервер1 и сервер1-сервер2.

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

Например, представьте, что клиент загружает большой файл на сервер. Как правило, окно отправки управления потоком клиента маленькое, скажем, по умолчанию 65535 октетов. Клиент может отправить только до 65535 октетов, прежде чем загрузка будет остановлена.

Эти 65535 октетов получены server1. Теперь server1 становится клиентом, чтобы общаться с server2. Давайте представим, что клиент server1 был настроен с гораздо меньшим окном управления потоком, когда он связывается с server2, скажем, всего 16384 октета.

В этом примере server1 останавливает загрузку в server2 после 16384 октетов и должен сохранять оставшиеся 65535-16384 октетов, ожидая, пока server2 уведомит (через кадр WINDOW_UPDATE) о том, что загруженные данные были использованы.

Когда клиент server1 получает WINDOW_UPDATE от server2, он может отправить дополнительные данные server2; но также он должен решить, отправить ли клиенту WINDOW_UPDATE (поскольку его окно управления потоком с клиентом теперь имеет место для дополнительных 16384 октетов) или подождать еще немного. Например, он может отправить еще 16384 октета на server2, и только после получения второго WINDOW_UPDATE от server2 может решить отправить клиенту WINDOW_UPDATE (с обновлением 16384+16384 октетов).

Как видно из приведенного выше примера, управление потоком между клиентом и server1 связано с управлением потоком между server1 и server2, но не зависит от него.

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

person sbordet    schedule 22.11.2016
comment
Извините, это опечатка, я знаю, что h2 используется чаще, чем h2c. - person laike9m; 23.11.2016
comment
Хороший ответ. Есть ли определение посредников где-нибудь в RFC7540 или других RFC? - person laike9m; 23.11.2016
comment
Не то, чтобы я знал, но для обработки управления потоком посредник должен декодировать и повторно кодировать кадры HTTP/2. Поэтому сетевые элементы (коммутаторы, прокси и т. д.) между клиентом и сервером, использующие h2, исключаются, поскольку они просто передают зашифрованные байты, а не кадры HTTP/2. - person sbordet; 23.11.2016
comment
А как же h2c? Я знаю, что он редко используется, но, поскольку он не зашифрован, посредники также должны иметь возможность управлять потоком. - person laike9m; 24.11.2016
comment
С h2c посредник должен решить, следует ли а) быть непрозрачным, поэтому просто брать байты и пересылать их, или б) интерпретировать h2c и, следовательно, также применять правила управления потоком. Обычно это происходит при обмене данными между серверами, когда вам может не понадобиться шифрование в одном и том же центре обработки данных. - person sbordet; 29.11.2016

Это зависит от значения прыжков/посредников.

Если посредники находятся на более низких уровнях (шлюзы TCP, NAT, коммутаторы и т. д.), то они прозрачны для HTTP/2, поскольку управление потоком HTTP/2 применяется сквозным образом между клиентом HTTP/2 и сервером. Отдельные переходы между ними могут использовать механизмы управления потоком более низкого уровня.

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

В случае HTTP-прокси вы даже сталкиваетесь с ситуациями, когда вы проксируете HTTP/1.1 в HTTP/2 и наоборот. В этих ситуациях они будут использовать механизмы управления потоком HTTP/2, чтобы гарантировать управление потоком для этого прыжка, и использовать управление потоком TCP, чтобы обеспечить управление потоком на другом прыжке. Если тип протокола правильно инкапсулирован в прокси-приложении (что означает, что он будет обеспечивать потоковые операции, учитывающие управление потоком для типов Request и Response), то проксирование потоков между различными типами протоколов не должно быть слишком сложным.

person Matthias247    schedule 23.11.2016