Pull to refresh

Comments 45

>>Вступлением" эту штуку я обозвал сам.
Преамбула?

я прямо чувствую всю боль автора от того что такой великолепный труд получил настолько ничтожный фидбек в виде плюсов и комментов.

Статья великолепная на самом деле и очень познавательная.

Но ведь согласитесь, со временем всё меньше и меньше тех, кто действительно работает с данными на таком уровне.)

С другой стороны, вы не можете отрицать, что это крайне важно, чтобы унтерменши вроде меня не могли ставить плюсы на Хабре, даже хорошим статьям. PS Но комментарий писать могу, это другое.

За прошедшие 2 месяца кто-то плюсанул мне в карму, я смог поставить несколько плюсцов хорошим статьям, а потом кто-то минусанул, и я опять лишь остроумно комментирую. Вот такая история жизни.

В эру http3/quic, http2 уже не так интересен, но статья -бомба, но увы, для гиков.

Не соглашусь, всё-таки HTTP/3 и QUIC сравнительно новые, ещё не обжились инфраструктурой. Особенно QUIC: учитывая, что сейчас клиент, отправляя пакеты QUIC не может быть уверен, дойдёт ли он хоть куда-нибудь, будет ли принят сервером или отвалится где-то по пути из-за файерволов, соединение HTTP/3 всё равно приходится начинать с соединения HTTP/2. Не на всех языках даже есть реализации клиентов/серверов HTTP/3 из-за терок с openssl. Взять тот же NodeJS, там библиотека для работы с QUIC всё ещё в разработке. Плюс HTTP/3 толком от 2 версии не отличается, по большому счёту просто вся чепуха с мультиплексированием перенесена с прикладного уровня на транспортный.

Ну и я полагаю позиция комитета по HTTP такая, что все три версии протокола сосуществуют, а не заменяют друг друга. Всё-таки чем дальше в лес, тем больше дров непонятно, зачем упарываться с бинарным HTTP/2, если вы пишете hello world для портфолио, там и HTTP/1.1 прекрасно справляется. Так же с HTTP/3, всё-таки TCP не без недостатков, но проверен временем. Зачем лезть в трясину QUIC, если HTTP/2 даёт достаточный выигрыш во что вы там ни играли.

Во-первых, огромное человеческое спасибо за статью!

Во-вторых, не очень понятно, в чём же выигрыш http2 по сравнению с http1.1 на практике. Кажется, передать текстом GET / выходит как-то быстрее, чем вот это вот всё. Свою ошибку c мультиплексированием внутри TCP гугол признал (и выпустил http/3)

Не за что)

Бенчмарки все поголовно говорят, что http2 быстрее, у кого-то в 2 раза, у кого-то в 1.001. Так что, по крайней мере, если вы играете в бенчмарки, выигрыш есть) А есть ли на самом деле ну надо смотреть на конкретном сайте и целевой аудитории.

И, кстати, запрос GET / HTTP/1.1\r\n\r\n в http2, если использовать HPACK по уму, а не как я описывал, записывается 00 00 03 01 05 00 00 00 01 12 14 17 — 12 байтов вместо 18, считайте, на треть меньше B). А оценивать более содержательные запросы и включать в оценку преамбулу не будем, чтобы не портить статистику.

Quic уже встроен в браузеры, уже есть миллиард реализации rfc9000, у хромиума есть все, чтобы каждый желающий его прикрутил, для квика можно обойтись и без tcp хендшейков, шифрование там очень даже интересное. Сейчас не 2005 чтобы говорить о зарезанном udp на фаерволлах. У квика есть преимущество - вы можете сделать свой контроль доставки, так сказать свой congestion control, в tcp же это на уровне ядра или qbic или bbr

 так сказать свой congestion control, в tcp же это на уровне ядра или qbic или bbr

не можете, а вынуждены делать в user space, а раньше это жило в kernel space. Каждый переход юзер/кернел весьма дорог, и вынос этого сетевого уровня из ядра оборачивается бОльшей нагрузкой на CPU

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

Ну и возможность пропатчить алгоритм congestion control простым обновлением либы, вместо обновления kernel, дорогого стоит.

В эру http3/quic

In soviet Russia quic, увы, выдают по талонам

Я не осилил впш сарказм, я в рф и у меня квик :) все в свободном доступе. Боьше скажу, я сделал прототип своего стриммингово сервиса на квике, андройд приложение, nginx с квиком и бакенд, вебсокеты и стримы идут по udp и отлично работает.

Ну вот прям сейчас проверил. Белый список сайтов (проверял гугл, яндекс, вк) работают по http3, сайты попроще уже нет.

Ходят слухи, что тщ майор пока не умеет этот самый квик расшифровывать, поэтому вот так, белым списком.

Где вы добыли некий такой "белый список"? Пруфы пожалуйста:)

Кто знает правильный ответ, тот получит 10 лет:)

Вам повезло. Но без шуток была история когда тор что-то там то ли отправлял то ли получал через quic и ркн заблочили всё что использовало libquic. При этом гошная реализация quic продолжала и вроде пока продолжает работать. Возможно и ещё какие-то.

Не обязательно для гиков, вот сейчас пишу мини библиотеку для микроконтроллера SV32WB06 на просто C и именно как раз по байтам приходится разбирать тело пакета

спасибо, статья - замечательная!

Отличная статья, спасибо!

Вот еще бы такую же по TLS…

Думал об этом, возможно будет :) Если будет, оставлю тут ссылку

И HTTP/3 с QUIC :)
Спасибо большое за статью!

+WebSocket :)

Всё, загрузили человека заказами. :-D

Статья отличная. Но зачем был придуман TCP с кривыми отступами полей заголовков поверх TCP, вместо того чтобы просто пользоваться самим TCP (или, допустим, его расширением MPTCP) остаётся загадкой.

Не понял, что вы имеете в виду под "кривыми отступами полей заголовков" и при чём здесь TCP. HTTP/2 не стремится заменить TCP ни в какой интерпретации

Не понял, что вы имеете в виду под "кривыми отступами полей заголовков"

В традиционных протоколах отступ кратен его длине. Например, поле из 32-х бит будет расположено в 4-х, 8-и, 12-и, и т.д. байтах от начала пакета. Во всяком случае, если в этом поле целое количество октетов.

Заголовок TCP-пакета, на пример

Таким образом при обработке эти поля можно прямо сразу считать готовой структурой работать с заголовком в памяти напрямую. В случае http/2 это приведёт ко множественным невыровненным чтениям и потере производительности на ровном месте. Потому что Stream Identifier смещён на 5 байт вместо 4-х, а содержимое ­— на 9, вместо 8-и.

HTTP/2 не стремится заменить TCP ни в какой интерпретации

Естественно, нет. Но там реализованы все те же самые концепции. Вместо пары портов по 16 бит, есть один Sequence Identifier в 32 бита. Есть пинги. Есть управление окном доставки. Заменить отдельные потоки TCP-соединениями, пинги на keepalive, управление окном на ... управление окном и от http/2 не останется примерно ничего.

Таким образом при обработке эти поля можно прямо сразу считать готовой структурой работать с заголовком в памяти напрямую.

Не скажу, что я эксперт в низкоуровневом программировании, но как-то мне не верится, что сколько-нибудь значительного улучшения производительности можно было бы достичь с выровненным заголовком. Для tcp ещё могу понять: там содержимое заголовков — это набор чиселок, а содержимое пакета вообще не имеет значения, соответственно чиселки проще считывать, когда они выровнены. А реализации http2 интерпретируют содержимое кадров не как просто чиселки. В плане, как ни крути, реализации http2 работают на прикладном уровне, значит они читают все данные: и заголовок кадра, и содержимое, — из системного буфера tcp в условный массив. Даже если заголовок кадра был бы, допустим, 16 байтов, http-заголовки всё равно записаны чёрт знает как, у них всех разная длина, и значения могут быть произвольные. Так что чтобы от выровненного заголовка кадра был смысл, надо чтобы и http-заголовки были выровнены, а это трата места. И вообще, HTTP/2 пытается оптимизировать использование трафика и, пусть и не слишком удачно, количество необходимых tcp соединений, а не скорость обработки: мне кажется любые выигрыши производительности, которые можно было бы достигнуть выравниванием, мгновенно нивелируются, например, затратами на распаковку HPACK.

Заменить отдельные потоки TCP-соединениями, пинги на keepalive, управление окном на ... управление окном

И вы получите HTTP/1.1 с его недостатками, которые гугл попытался исправить в HTTP/2?) Не хочу сказать, что http2 хороший протокол. То, что возникли проблемы из-за попытки отправлять кучу запросов по одному TCP соединению, и так понятно, это упоминается в каждой статье с обзором http3. Собственно для этого и пришлось разрабатывать quic. Но если у вас вопрос "зачем был нужен такой протокол", то ответ — не совсем удачная попытка избавиться от проблем http1.1, которая перелилась в http3 — пока не совсем ясно, насколько удачную попытку избавиться от проблем http2.

Я таки не смог уследить, как, как вы перешли с протокольного уровня на транспортный да еще и перемешали их? Единственный, кто выступает симбиозом - quic.

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

все описанные возможности http/2 есть в простом обычном TCP. Соответственно, http/2 — это новый TCP поверх классического

Ну как, то, что есть похожие принципы работы не значит, что http2 это tcp в tcp. Всё-таки цели разные: tcp потоковый протокол, http2 основан на обмене сообщениями. Почему http2 тогда работает поверх tcp? Потому что выбирать приходится только из tcp и udp, либо изобретать свой транспортный протокол, а это головная боль. udp не подходит, потому что реализовывать надёжную доставку пакетов тоже головная боль, а tcp её предоставляет и проверен временем.

Теперь, вроде как у нас от tcp есть целый поток по которому отправляй данные не хочу, а мы только одно сообщение отправили и ждём, давайте этот поток использовать по полной. Для этого прилепим к каждому сообщению идентификатор и будем отправлять их целую кучу. Новая проблема: сообщения можно отправлять только целиком, ну так давайте разобьём их на более мелкие кадры. Вот и вышел http2, по мне так из вполне логичных и обоснованных рассуждений. Другое дело, что эти простые и очевидные решения оказались не совсем совместимы с реальностью, и что тот "целый поток" плохо справляется с грудой сообщений которые мы по нему теперь отправляем. Тут уже ничего не остаётся, кроме как придумывать новый транспортный протокол, собственно чем и занялись в http3. В общем, понятиями конечно http2 и tcp оперируют очень похожими, но в историческом контексте, я считаю, решения вполне обоснованные.

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

Или просто откроем два (или двадцать два) TCP-соединения и будем делать тоже самое.

Новая проблема: сообщения можно отправлять только целиком, ну так давайте разобьём их на более мелкие кадры

Если использовать отдельное TCP-соединение на поток, то "Новая проблема" вообще не возникает

Заодно, получаем все остальные возможности, описанные в статье забесплатно.

Осталось переделать текстовый протокол в бинарный, сделать человеческое (по сравнению с http/1) управление соединениями и забанить нешифрованые соединения.

Или просто откроем два (или двадцать два) TCP-соединения и будем делать тоже самое.

Так и жили с http1.1, и одной из целей http2 как раз было избавиться от кучи TCP-соединений. Во вступлении RFC об этом речь

The resulting protocol [HTTP/2] is more friendly to the network because fewer TCP connections can be used in comparison to HTTP/1.x. This means less competition with other flows and longer-lived connections, which in turn lead to better utilization of available network capacity. Note, however, that TCP head-of-line blocking is not addressed by this protocol.

Вот, допустим, накидали причин, почему множество TCP-соединений это неоптимально.

Так и жили с http1.1, и одной из целей http2 как раз было избавиться от кучи TCP-соединений

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

Вот, допустим, накидали причин, почему множество TCP-соединений это неоптимально.

Их там же и опровергли, как несостоятельные.

Единственная реальная проблема с множеством долгоживущих TCP-соединений состоит в том, что могу закончится порты: между двумя хостами может существовать только 65000 соединений к порту 443. Соответственно, если есть какой-то очень большой сегмент за NAT, то очередное соединение может просто не установится. Но эта проблема точно так же [не] существует в http/2, ведь там тоже долгоживущие соединения. Просто их меньше.

Ох уже эти октеты, видимо слово "байт" для быдла

Там же прямо в статье написано:

Так как по определению (по крайней мере изначальному) байт не обязательно состоит из восьми бит, а октет — обязательно, то при обсуждении сетевых протоколов принято использовать именно октет. И я буду, чем я хуже.

Слово «байт» также немного дискредитировано тем, что в разных языках он то signed, то unsigned; короче, нет акцента на логической равноправности всех битов. А у слово «октет» такой проблемы нет.

Sign up to leave a comment.