Spec-Zone.ru › HTTP

Управление соединениями в HTTP 1.x

Управление соединениями в HTTP/1.x

Управление соединениями — важная тема в HTTP: открытие и поддержание соединений во многом влияет на производительность веб-сайтов и веб-приложений. В HTTP/1.x существует несколько моделей: кратковременные соединения, постоянные соединения и конвейеризация HTTP.

В качестве транспортного протокола HTTP в основном использует TCP, обеспечивающий соединение между клиентом и сервером. На заре своего развития HTTP использовал единственную модель обработки таких соединений. Эти соединения были кратковременными: новое соединение создавалось при каждой отправке запроса и закрывалось после получения ответа.

Эта модель имела существенное ограничение производительности: открытие каждого TCP-соединения требует значительных ресурсов. Между клиентом и сервером необходимо обменяться несколькими сообщениями. Сетевая задержка и пропускная способность влияют на производительность при отправке запроса. Для предоставления всего необходимого объёма информации современным веб-страницам требуется множество запросов (дюжина или больше), что делает эту раннюю модель неэффективной.

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

Compares the performance of the three HTTP/1.x connection models: short-lived connections, persistent connections, and HTTP pipelining.

Примечание: В HTTP/2 добавлены дополнительные модели управления соединениями.

Важно отметить, что управление соединениями в HTTP относится к соединению между двумя соседними узлами, то есть действует от узла к узлу, а не от конца до конца. Модель соединения между клиентом и первым прокси может отличаться от модели соединения между прокси и целевым сервером (или любыми промежуточными прокси). Заголовки HTTP, участвующие в определении модели соединения, такие как Connection и Keep-Alive, относятся к заголовкам, действующим от узла к узлу, и их значения могут изменяться промежуточными узлами.

С этой темой связано понятие обновления соединения HTTP: соединение HTTP/1.1 обновляется до другого протокола, например TLS/1.0, WebSocket или даже HTTP/2 без шифрования. Этот механизм обновления протокола подробнее описан в другом разделе.

Кратковременные соединения

Исходная модель HTTP, а также модель, используемая по умолчанию в HTTP/1.0, — это кратковременные соединения. Каждый запрос HTTP выполняется в отдельном соединении; это означает, что перед каждым запросом HTTP выполняется TCP-рукопожатие, а сами запросы отправляются последовательно.

Само TCP-рукопожатие требует времени, но TCP-соединение адаптируется к нагрузке и становится эффективнее при длительном использовании (то есть при «прогретом» соединении). Кратковременные соединения не используют эту особенность TCP, поэтому производительность оказывается ниже оптимальной: данные приходится снова и снова передавать по новым, «холодным» соединениям.

Эта модель используется по умолчанию в HTTP/1.0 (если заголовок Connection отсутствует или его значение задано как close). В HTTP/1.1 эта модель используется только в том случае, если заголовок Connection передан со значением close.

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

Постоянные соединения

У кратковременных соединений есть два существенных недостатка: для установления нового соединения требуется значительное время, а производительность базового TCP-соединения повышается, только когда оно используется в течение некоторого времени (то есть становится «прогретым»). Чтобы уменьшить влияние этих проблем, ещё до появления HTTP/1.1 была разработана концепция постоянного соединения. Его также называют keep-alive-соединением.

Постоянное соединение остаётся открытым в течение некоторого времени и может повторно использоваться для нескольких запросов, избавляя от необходимости выполнять новое TCP-рукопожатие и позволяя использовать возможности TCP для повышения производительности. Такое соединение не остаётся открытым бесконечно: соединения, простаивающие бездействуя, закрываются спустя некоторое время (сервер может использовать заголовок Keep-Alive, чтобы указать минимальное время, в течение которого соединение должно оставаться открытым).

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

По умолчанию соединения HTTP/1.0 не являются постоянными. Если установить для заголовка Connection любое значение, кроме close, обычно retry-after, соединение станет постоянным.

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

Конвейеризация HTTP

Примечание: В современных браузерах конвейеризация HTTP по умолчанию не включена:

  • Ошибочно работающие прокси по-прежнему встречаются часто и приводят к странному и непредсказуемому поведению, которое веб-разработчикам трудно предвидеть и диагностировать.
  • Правильно реализовать конвейеризацию сложно: на выигрыш от конвейера напрямую влияют размер передаваемого ресурса, фактическое значение RTT и пропускная способность. Если эти параметры неизвестны, важные сообщения могут задерживаться за неважными. Более того, представление о важности меняется по мере построения страницы! Поэтому в большинстве случаев конвейеризация HTTP даёт лишь незначительное улучшение.
  • Конвейеризация подвержена проблеме блокировки начала очереди.

По этим причинам конвейеризацию вытеснил более совершенный алгоритм — мультиплексирование, используемое в HTTP/2.

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

Конвейеризация — это отправка последовательных запросов по одному и тому же постоянному соединению без ожидания ответа. Это позволяет избежать задержек, связанных с соединением. Теоретически производительность можно также повысить, если упаковать два запроса HTTP в одно TCP-сообщение. Типичное значение MSS (максимальный размер сегмента) достаточно велико, чтобы вместить несколько простых запросов, хотя размер запросов HTTP продолжает расти.

Конвейеризацию можно применять не ко всем типам запросов HTTP: безопасно повторно отправлять можно только идемпотентные методы: GET, HEAD, OPTIONS, TRACE, PUT и DELETE. Если произойдёт сбой, содержимое конвейера можно отправить повторно.

Сегодня все прокси и серверы, соответствующие HTTP/1.1, должны поддерживать конвейеризацию, хотя на практике у многих есть ограничения. Это одна из важных причин, по которым ни один современный браузер не включает эту возможность по умолчанию.

Шардирование доменов

Примечание: Если у вас нет особой неотложной необходимости, не используйте этот устаревший приём; вместо него перейдите на HTTP/2. В HTTP/2 шардирование доменов больше не нужно: соединение HTTP/2 хорошо справляется с параллельными запросами без заданного приоритета. Шардирование доменов даже снижает производительность. В большинстве реализаций HTTP/2 используется метод, называемый объединением соединений, который отменяет возможное шардирование доменов.

Поскольку соединение HTTP/1.x передаёт запросы последовательно, даже если их порядок не задан, оно не может работать оптимально без достаточной пропускной способности. В качестве решения браузеры открывают несколько соединений с каждым доменом и отправляют параллельные запросы. Раньше по умолчанию использовалось от 2 до 3 соединений, но сейчас чаще открывают 6 параллельных соединений. Попытка открыть больше соединений может привести к срабатыванию защиты от DoS-атак на стороне сервера.

Если серверу нужно ускорить ответ веб-сайта или приложения, он может принудительно открыть больше соединений. Например, вместо размещения всех ресурсов в одном домене, скажем www.example.com, их можно распределить по нескольким доменам: www1.example.com, www2.example.com, www3.example.com. Каждый из этих доменов указывает на тот же сервер, и веб-браузер откроет по 6 соединений с каждым из них (в нашем примере общее число соединений увеличится до 18). Этот приём называется шардированием доменов.

Without domain sharding, a client requests six images from a domain with a maximum of two requests taking place in parallel. With domain sharding, the images are available from two domains and the client can run four requests in parallel, downloading the images in less time.

Заключение

Улучшенное управление соединениями позволяет значительно повысить производительность HTTP. При использовании HTTP/1.1 или HTTP/1.0 наилучшую производительность обеспечивает постоянное соединение, по крайней мере до тех пор, пока оно не перейдёт в состояние простоя. Однако неудача конвейеризации привела к разработке более совершенных моделей управления соединениями, которые были включены в HTTP/2.

См. также

  • Эволюция HTTP
  • Термины глоссария:
    • HTTP
    • HTTP/2
    • QUIC
    • Время кругового обхода (RTT)
    • Медленный старт TCP
    • TLS
    • Протокол управления передачей (TCP)

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Connection_management_in_HTTP_1.x

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API