В этом посте я объясню, как работает Интернет. Мы ответим на вопросы наподобие «Как браузер находит файл HTML для запрошенной веб-страницы?», «Как файл HTML превращается в интерфейс пользователя?», «Что можно сделать, чтобы ускорить этот процесс?», «Как устанавливается и поддерживается связь с сервером?», а также рассмотрим следующие концепции:
- Клиент-серверную модель
- Жизненный цикл запроса веб-страницы
- Hypertext Transfer Protocol
- Как браузеры рендерят контент
Клиент-серверная модель
Термин "клиент-серверная модель" — это обобщённое понятие, описывающее взаимодействие друг с другом двух компьютеров; один из компьютеров является клиентом, запрашивающим информацию, другой — сервером, отправляющим эту информацию. Эту модель можно использовать во множестве различных проектов, и одним из самых популярных примеров его применения является Интернет.
Когда мы пытаемся перейти на какой-нибудь веб-сайт, допустим, на linkedin.com, то наш браузер превращается в клиент. Он выполняет запрос к серверу. Сервер создаётся LinkedIn. Когда кто-то создаёт веб-сайт, он должен содержать этот веб-сайт на каком-то сервере. Иногда для этого используется поставщик облачных услуг наподобие AWS или Azure, или же можно создать сервер самостоятельно.
Сервер будет отправлять клиенту HTML, после чего клиент, который, повторюсь, является обычным веб-браузером, интерпретирует этот HTML и генерирует пользовательский интерфейс. Пока вы продолжаете пользоваться linkedin.com и взаимодействовать со страницей, браузер продолжает обмениваться данными с сервером.
Иногда один компьютер может быть в двух разных взаимодействиях и клиентом, и сервером. Например, одна машина может быть сервером для конечных пользователей и клиентом для базы данных.
Жизненный цикл запроса веб-страницы
Что же происходит, когда мы переходим на linkedin.com? Что делает браузер, чтобы запросить HTML для этой страницы с сервера LinkedIn? Чтобы ответить на эти вопросы, нам сначала нужно взглянуть на её URL. Полный URL может выглядеть примерно так:
https://www.linkedin.com:443/feed
. Давайте его разберём.-
HTTPS
— это протокол, определяющий, как будет отформатирован этот запрос. HTTPS и HTTP — это стандартные протоколы для обмена данными в Интернете. - После протокола идут двоеточие и две косые черты, затем поддомен, а также доменное имя.
linkedin.com
— это доменное имя, а также имя веб-сайта.www
— это поддомен, его можно воспринимать как домен внутри домена linkedin. Доменное имя разбито на имя веб-сайта и домен верхнего уровня, то есть часть.com
. Большинство доменов верхнего уровня связано с какой-нибудь страной. - Далее указан порт
443
, который можно не указывать, потому что это стандартный порт. Для HTTPS по умолчанию используется порт 443, а для HTTP — 80. В URL почти никогда не требуется указывать порт. - Затем идёт путь к ресурсу, который мы запрашиваем. Если вы просто запрашиваете домашнюю страницу, то большинство серверов позволяет не указывать путь. Однако если вам нужен конкретный ресурс, например, лента новостей LinkedIn, то нужно будет добавить косую черту и путь
feed
.
Мы рассмотрели основные части URL, но он может включать в себя и другие элементы. Например, параметры запросов — пары «ключ-значение», которые мы передаём серверу, чтобы предоставить ему больше информации, обычно для фильтрации контента. Также можно добавить фрагмент. В нём используется символ фунта
#
, после чего добавляется ID какого-то элемента в HTML и браузеры обрабатывают это, по умолчанию выполняя скроллинг к этому элементу.Разобравшись с URL, нам нужно найти сервер и отправить ему запрос HTML. Когда вам нужно отправить запрос к серверу, вы знаете, что его доменное имя linkedin.com, но необходимо ещё и определить адрес этого сервера. Его можно узнать при помощи IP-адреса. Это уникальный идентификатор компьютера в Интернете. Для поиска IP-адреса нужного домена используется Domain Name System (DNS, система доменных имён).
Когда браузер ищет IP-адрес веб-сайта, сначала он проверяет локальный кэш. Операционная система на вашей машине хранит локальный кэш каждого IP-адреса, который недавно был обнаружен при помощи DNS. Благодаря этому, ей не приходится выполнять повторные сетевые запросы. Если IP-адрес не найден в локальном кэше, в сеть передаётся DNS-запрос.
Сначала этот запрос передаётся на сервер ресолвинга имён, который проверяет собственный кэш. Сервер ресолвинга имён (resolving name server) обычно принадлежит вашему Интернет-провайдеру. Далее, если сервер ресолвинга имён не знает IP-адреса, то он будет искать корневой сервер имён. На этом сервере хранятся сопоставления доменов верхнего уровня наподобие
.com
с IP-адресами серверов доменных имён верхнего уровня. Для каждого домена верхнего уровня существует сервер, который знает, как найти IP-адреса всех доменов, зарегистрированных в этом домене верхнего уровня.Корневой сервер имён может сообщить серверу ресолвинга имён, где искать, и где находится сервер домена верхнего уровня. Сервер ресолвинга имён использует эту информацию для выполнения запроса к нужному серверу доменных имён верхнего уровня (серверу имён TLD). Мы достигли сервера доменов верхнего уровня, который перенаправит нас на полномочный сервер имён. Полномочный сервер имён (authoritative name server) знает IP-адрес домена, который мы ищем, поэтому он отправит этот IP-адрес серверу ресолвинга имён, который, в свою очередь, вернёт его вашему компьютеру, и браузер будет знать, где искать.
Теперь мы знаем IP-адрес linkedin.com, но у нас возникает следующий вопрос: как браузер подключается к linkedin.com? Каким образом два компьютера связываются друг с другом? Это соединение происходит по TCP, что расшифровывается как Transmission Control Protocol. Это сетевой протокол, используемый для установки соединения между двумя компьютерами в Интернете. TCP — это основной механизм доставки HTTP-запросов. Он передаёт информацию от одного компьютера другому при помощи пакетов. Это небольшой фрагмент данных, часть большего фрагмента данных; пакеты объединяются вместе, образуя передаваемый большой фрагмент данных.
Чтобы создать TCP-соединение, клиент должен инициировать подключение. Клиент делает это, отправляя пакет синхронизации (SYN), а сервер отвечает клиенту подтверждением синхронизации. Затем клиент отвечает серверу, подтверждая, что получил подтверждение синхронизации. Это называется подтверждением клиентом и сервером, а также трёхэтапным рукопожатием (three-way handshake).
После этого два компьютера подключены друг к другу по TCP, поэтому могут начать передавать HTTP-сообщения. Когда пользователь уходит с веб-сайта, соединение завершается. Для завершения этого TCP-соединения каждая из сторон отправляет другой стороне пакет завершения (fin), который другая сторона подтверждает. Это обозначает завершение соединения.
Hypertext Transfer Protocol (HTTP)
HTTP — это стандартный сетевой протокол, используемый для отправки запросов и ответов в вебе. HTTP-запросы в общем случае состоят из трёх компонентов:
- Строка запроса — включает в себя метод, путь и версию HTTP
- Заголовки — содержат пары «ключ-значение» дополнительной информации для сервера
- Тело — содержимое запроса, например, новые данные, загружаемые в POST-запросе.
HTTP-ответы соответствуют тому же стандартному формату, что и запросы, однако в верхней строке (строке состояния) отсутствует метод и путь. В этой строке содержится код состояния и сообщение. Например, код состояния 200 с сообщением OK включается в ответ на успешный GET-запрос.
Распространённые методы запросов:
- GET-запрос — это запрос серверу с просьбой отправки какой-то информации.
- POST-запрос используется, когда клиент отправляет информацию на сервер.
- PUT заменяет данные на сервере
- DELETE удаляет данные с сервера
- PATCH частично обновляет данные на сервере
- HEAD — это то же самое, что и GET, но без тела
Распространённые коды состояния, которые сервер может отправлять в качестве ответа:
- 200: OK (запрос выполнен)
- 201: создан (часто с POST-запросами)
- 301: перемещён навсегда (перенаправление)
- 302: обнаружен (перемещён временно)
- 400: плохой запрос
- 401: не авторизован (без аутентификации)
- 403: запрещён (у клиента отсутствует доступ к тому, что он пытается использовать)
- 404: не найден (указанный путь не содержит ресурса)
- 500: внутренняя ошибка сервера
- 503: сервис недоступен (если сервер отключён на запланированное обслуживание)
В HTTP не реализована конфиденциальность. Маршрутизаторы и промежуточные устройства, контролируемые вашим провайдером Интернета, а также веб-сайты могут читать и изменять всю информацию, передаваемую по HTTP, в том числе HTTP-заголовки, IP-адреса отправителя и получателя, и даже данные ответа. Причина этого заключается в том, что HTTP не зашифрован.
Hypertext Transfer Protocol Secure (HTTPS) — это расширение HTTP, используемое для безопасных онлайн-коммуникаций. Этот протокол требует, чтобы у серверов были доверенные сертификаты и чтобы они использовали Transport Layer Security (TLS) — протокол безопасности, надстроенный поверх TCP и предназначенный для шифрования данных, передаваемых между клиентом и сервером.
Перед передачей HTTP-сообщения по сети HTTPS оборачивает его в зашифрованные конверты. HTTPS скрывает тело сообщения и HTTP-заголовки, но не IP-адреса отправителя и получателя, показывающие, какие узлы общаются друг с другом.
Как браузеры рендерят контент
Что делает браузер с файлами HTML, получив их от сервера? Как он превращает этот HTML в страницу, с которой может взаимодействовать пользователь? Процесс получения файла HTML и его преобразования в пользовательский интерфейс называется критическими этапами рендеринга (critical rendering path). Всего существует пять критических этапов рендеринга:
- Парсинг HTML, создание дерева DOM и запросы всех найденных ресурсов (изображений, скриптов, шрифтов и таблиц стилей).
- Парсинг CSS в дерево CSS Object Model (CSSOM).
- Объединение DOM и CSSOM в дерево рендеринга, содержащее информацию об узлах, которые будут рендериться на странице.
- Вычисление структуры (ширины, высоты, местоположения) узлов на основании размера вьюпорта.
- Отрисовка экрана на основании дерева рендеринга и вычислений структуры.
▍ Динамические изменения
Что происходит, когда JavaScript пытается изменить какие-то элементы на странице? Мы можем разделить такие изменения на три типа:
- Изменение цвета: узел будет перерисован, это очень быстрая операция.
- Изменение позиции: повторный перерасчёт и перерисовка изменённого узла и одноуровневых узлов.
- Крупные изменения: повторный перерасчёт и перерисовка всей страницы.
На этапе парсинга HTML браузер находит различные ресурсы и запрашивает их, например, изображения. Но в случае высокоприоритетных ресурсов наподобие таблиц стилей и скриптов, которые необходимы для работы страницы, используется нечто под названием сканер предварительной загрузки (pre-load scanner). Во время парсинга HTML он проходит по HTML в поисках всех ресурсов, имеющих высокий приоритет, и делает к ним HTTP-запросы ещё в процессе парсинга. Благодаря этому, нам не приходится ждать возврата этих запросов, как бы это происходило, если бы HTML искал их.
▍ Оптимизация под критические этапы рендеринга
Что же мы можем сделать для оптимизации своего кода? Вот несколько идей:
- Использовать defer/async-скрипты — смысл заключается в том, чтобы скрипты не мешали рендерингу.
- Минимизировать размер DOM — чем глубже идёт наш код HTML, тем сложнее должно быть дерево DOM и тем дольше занимает парсинг такого HTML. Однако никогда не стоит жертвовать accessibility.
- Уменьшить размеры файлов при помощи сжатия/минификации.
- Использовать ленивую загрузку — определите, какой минимальный объём контента требуется вашей странице и не запрашивайте всё за раз. Когда страница становится интерактивной, начинайте запрашивать дополнительные ресурсы в фоновом режиме.
-
Анимации с аппаратным ускорением — анимации сложны и способны сильно замедлить страницу. Если у вас есть замедляющая страницу анимация, то можно повысить её скорость рендеринга, добавив CSS-правило
transform:translate 3D(0,0,0)
. Это один из способов, которым можно сообщить браузеру, что необходимо использовать композитинг. При работе с трёхмерным пространством нам нужно выстраивать элементы послойно. Когда браузер выполняет это выстраивание, он понимает, насколько сложна анимация и применяет её аппаратное ускорение. Он будет обрабатывать её в GPU, а не в CPU, что обычно повышает производительность. Можно воспользоваться этим способом, если у вас есть проблемы со скоростью рендеринга анимаций.
Это ключевые концепции, необходимые для понимания работы веба. Надеюсь, они будут вам полезны.
???? Голосуй за нас на премии «ЦОДы РФ»!
Комментарии (16)
saga111a
00.00.0000 00:00+9Статья очень слабая, указанные тут вещи почти везде рассказываются. Больше вопросов, как создается эта TCP связь, как сервер понимает кому что отдавать, как проходятся пакеты из сети в NAT когда под одним IP сидят множество устройств. Очень много вещей которые бы стоило показать в статье с таким заголовком, но их нет.
funca
00.00.0000 00:00+4Статья больше похожа на SEO кликбейт, с целью собрать внутри популярные ключевые слова и не спалиться. По содержанию пропущены важные структурные концепции (модель коммуникации OSI, например), поэтому выглядит как поток сознания какой-то нейронки.
s60
00.00.0000 00:00+1Статья больше похожа на SEO кликбейт
а какие еще статьи могут быть у хостинг-провайдера ....
imjustwatching
00.00.0000 00:00+5Это уже больше в модель оsi углубляться надо, как идет маршрутизация и как уровни OSI взаимодействуют с друг другом. Точно не в эту статью. Статья про основы, автор прошёлся по верхам, чтобы дать понять общие принципы, зачем излишне душнить то боже
s60
00.00.0000 00:00+1... и как несколько браузеров, работающих на 80 порту не путают кому какой пакет получать, и как передаются картинки, аудио и видео (встроенные в html страницу) ...
fk0
00.00.0000 00:00+2Далее, если сервер ресолвинга имён не знает IP-адреса, то он будет искать корневой сервер имён. На этом сервере хранятся сопоставления доменов верхнего уровня наподобие
.com
A вот и нет! Вначале он будет искать site.com в своём локальном домене, а потом только во всём интернете. Просто обычно в локальном домене нет того же google.com.internetprovider.net. Но может же быть! Разве я не прав? А чтоб такого не было, доменное имя должно содержать точку на конце: "google.com." И доменное имя с точкой в конце -- самое что ни на есть полное, и корректное.
fk0
00.00.0000 00:00+2символ фунта
#
В ASCII нет "символа фунта" (£).
Rive
00.00.0000 00:00Похоже, это артефакт перевода выражения pound sign, относящегося к знаку решётки; в свою очередь, в англоязычных странах это название указывает на то, что символ '#' эволюционировал от лигатуры для слов libra pondo (вес фунта), т.е. в некоторой степени действительно является символом фунта.
fk0
00.00.0000 00:00+8Это ключевые концепции, необходимые для понимания работы веба.
Слишком громко сказано. Намешано всего в кучу. Работа современного веб-браузера -- это вообще не веб, а загрузка аппликации в виртуальную машину... Гораздо лучше бы было показать на примере lynx и показать как telnet'ом можно выполнить HTTP-запрос, и где там заголовки, а где там html:
$ telnet altavista.com. 80 Trying 74.6.136.150... Connected to altavista.com. Escape character is '^]'. GET / HTTP/1.0 HTTP/1.0 400 Host Header Required Date: Mon, 06 Mar 2023 21:59:25 GMT Via: http/1.1 src2.ops.bf1.yahoo.com (ApacheTrafficServer) Server: ATS Cache-Control: no-store Content-Type: text/html Content-Language: en X-Frame-Options: DENY X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin Content-Security-Policy: sandbox allow-scripts; default-src 'self'; img-src https:; style-src 'unsafe-inline'; script-src 'unsafe-inline'; report-uri http://csp.yahoo.com/beacon/csp?src=redirect Content-Length: 4339 <!DOCTYPE html> <html lang="en-us"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <title>Yahoo</title> ...
И показать как пишется простейший html:
<html> <head> <title>Test</title> </head> <body> <center>Hello world!</center> <a src="http://www.altavista.com">search engine</a> </body> </html>
И показать как этот HTML можно увидеть в lynx/links. Без всяких там сложностей с асинхронной загрузкой скриптов.
И наконец вообще упомянуть, что современный HTML имеет корни в XML и SGML, а последний имеет в предках GML -- разработку IBM 80-х годов прошлого тысячелетия (когда никакого WWW ещё и в проекте не было). Да там тэги по-другому записываются, но очень похоже на ранний HTML.
А если говорить о Web, то основой веб является уж точно не загрузка приложения в виртуальную машину браузера, а ГИПЕРССЫЛКИ. Действительно стоящее изобретение Тима Бернеса Ли, в настоящее время практически похороненное т.н. "социальными сетями". В раннем интернете на любую страницу которую видел один пользователь можно было дать ссылку и она ему показывалась! (А сейчас нужна регистрация и SMS). И предполагалось, что весь Web будет семантически связан, все страницы между собой, ссылками. Страницы размещаемые на разных серверах разных организаций. И эти страницы они будут читаемыми, они будут специально размеченным текстом (а не загружаемыми с сервера приложениями, которые разным пользователям показывают разное). Вот суть веба. А то что сейчас -- вовсе и не веб...
Travisw
Вот одно и тоже везде, а как мне проверить что http методы работают корректно? Например вдруг ошибка? Это в postman или в консоли разработчика смотреть в браузере?
Travisw
И какие элементы html отвечают за эти методы get,post,put,delete и т.д.?
alcanoid
Если загуглить ваш комментарий полностью, в первой же строке выдачи будет статья с Хабра на тему HTTP-запросов, в которой есть и ответ на интересующий вас вопрос. Остаётся другой вопрос — интересующий ли?
Travisw
В вашем ответе нет ответа на вопрос. Там статья с описанием http в вакууме - без инструментов как в них порыться.
funca
В HTML есть элемент <form> с атрибутом method, который принимает только два значения: get и post.
Лет десять тому назад была попытка добавить новые методы - put, delete и т.п. Предложение даже попало в черновики HTML 5 и в каком-то виде было реализовано в Firefox. Но потом его отовсюду убрали. Вместо этого расширили API для работы с формами и отправки HTTP запросов из JavaScript - кому это очень нужно теперь могут сами себе напрограммировать.
Что касается корректности работы сервера, HTTP даёт лишь общие рекомендации. Поэтому набор критериев, что считать корректным, каждый сочиняет сам и потом пишет на это свой уникальный набор тестов, исходя из того, что насочинял.
fk0
Стоп. А как же WebDAV? Там по-моему именно через PUT файлы клались, а никак не через формы. Но да, вроде как PUT именно для HTTP/веба -- бесполезен.
funca
Я отвечал на вопрос про HTML, где используется лишь подмножество методов HTTP (из двух штук). WebDAV, ReST и т.п. это отдельная история.