Обратные прокси-серверы HTTP обычно включают HTTP Keep-Alive на стороне клиента прокси-соединения, а не на стороне сервера?

30

HAProxy имеет возможность включить поддержку активности HTTP на стороне клиента (client <-> HAProxy), но отключить его на стороне сервера (сервер HAProxy <->).

Некоторые из наших клиентов подключаются к нашему веб-сервису через спутник, поэтому задержка составляет ~ 600 мс, и я думаю, что, включив поддержку активности, это немного ускорит процесс. Я прав?

Это поддерживается Nginx? Это широко распространенная функция в других программных и аппаратных балансировщиках нагрузки? Что еще кроме HAProxy?

LostInComputer
источник

Ответы:

43

редактировать: мой ответ охватывает только исходный неотредактированный вопрос, который был типичным для такого рода вещей в балансировщиках нагрузки / обратных прокси. Я не уверен, что nginx / product X поддерживает это, 99,9% моего опыта обратного проксирования - с HAproxy.

Правильный. HTTP Keep-Alive на стороне клиента, но не на стороне сервера.

Зачем?

Если вы укажете несколько деталей, вы сможете быстро понять, почему это выгодно. Для этого примера давайте представим, что мы загружаем страницу www.example.com, и эта страница содержит 3 изображения, img [1-3] .jpg.

Загрузка страницы браузером без Keep-Alive

  1. Клиент устанавливает TCP-соединение с www.example.com через порт 80
  2. Клиент выполняет HTTP-запрос GET для "/"
  3. Сервер отправляет HTML-содержимое URI "/" (которое включает в себя HTML-теги, ссылающиеся на 3 изображения)
  4. Сервер закрывает TCP соединение
  5. Клиент устанавливает TCP-соединение с www.example.com через порт 80
  6. Клиент выполняет HTTP-запрос GET для "/img1.jpg"
  7. Сервер отправляет изображение
  8. Сервер закрывает TCP соединение
  9. Клиент устанавливает TCP-соединение с www.example.com через порт 80
  10. Клиент выполняет HTTP-запрос GET для "/img2.jpg"
  11. Сервер отправляет изображение
  12. Сервер закрывает TCP соединение
  13. Клиент устанавливает TCP-соединение с www.example.com через порт 80
  14. Клиент выполняет HTTP-запрос GET для "/img3.jpg"
  15. Сервер отправляет изображение
  16. Сервер закрывает TCP соединение

Обратите внимание, что 4 отдельных сеанса TCP установлены, а затем закрыты.

Загрузка страницы браузером с Keep-Alive

HTTP Keep-Alive позволяет одному TCP-соединению обслуживать несколько HTTP-запросов, один за другим.

  1. Клиент устанавливает TCP-соединение с www.example.com через порт 80
  2. Клиент выполняет HTTP-запрос GET для «/», а также просит сервер сделать этот сеанс HTTP Keep-Alive.
  3. Сервер отправляет HTML-содержимое URI "/" (которое включает в себя HTML-теги, ссылающиеся на 3 изображения)
  4. Сервер не закрывает TCP соединение
  5. Клиент делает и HTTP GET запрос для "/img1.jpg"
  6. Сервер отправляет изображение
  7. Клиент делает и HTTP-запрос GET для "/img2.jpg"
  8. Сервер отправляет изображение
  9. Клиент делает и HTTP GET запрос для "/img3.jpg"
  10. Сервер отправляет изображение
  11. Сервер закрывает TCP-соединение, если в течение периода ожидания Keep-Alive HTTP больше не получено ни одного HTTP-запроса

Обратите внимание, что с Keep-Alive только 1 TCP-соединение установлено и в конечном итоге закрыто.

Почему Keep-Alive лучше?

Чтобы ответить на этот вопрос, вы должны понимать, что нужно для установления TCP-соединения между клиентом и сервером. Это называется трехсторонним рукопожатием TCP.

  1. Клиент отправляет SYN (хронизированный) пакет
  2. Сервер отправляет обратно SYN (хронологию) ACK (присвоение), SYN-ACK
  3. Клиент отправляет пакет ACK (nowledgement)
  4. TCP-соединение теперь считается активным как клиентом, так и сервером

В сетях наблюдается задержка, поэтому каждый шаг трехстороннего рукопожатия занимает определенное время. Допустим, между клиентом и сервером есть 30 мс, отправка IP-пакетов назад и вперед, необходимая для установления TCP-соединения, означает, что для установления TCP-соединения требуется 3 x 30 мс = 90 мс.

Это может показаться не таким уж большим, но если учесть, что в нашем исходном примере нам нужно установить 4 отдельных TCP-соединения, это станет 360 мс. Что если задержка между клиентом и сервером составляет 100 мс, а не 30 мс? Тогда наши 4 соединения требуют 1200 мс для установления.

Хуже того, для загрузки обычной веб-страницы может потребоваться не более 3-х изображений, может быть несколько файлов CSS, JavaScript, изображений или других файлов, которые клиент должен запросить. Если страница загружает 30 других файлов и задержка клиент-сервер составляет 100 мс, сколько времени мы тратим на установление TCP-соединений?

  1. Для установления 1 TCP-соединения требуется 3 x задержки, т.е. 3 x 100 мс = 300 мс.
  2. Мы должны сделать это 31 раз, один раз для страницы и еще 30 раз для каждого файла, на который ссылается страница. 31 х 300 мс = 9,3 секунды.

9,3 секунды потратили на установление TCP-соединений для загрузки веб-страницы, которая ссылается на 30 других файлов. И это даже не учитывает время, потраченное на отправку HTTP-запросов и получение ответов.

С HTTP Keep-Alive нам нужно только установить 1 TCP-соединение, которое занимает 300 мс.

Если HTTP Keep-Alive настолько хорош, почему бы не использовать его и на стороне сервера?

Обратные прокси-серверы HTTP (такие как HAproxy) обычно развертываются очень близко к серверным серверам, для которых они проксируют. В большинстве случаев задержка между обратным прокси-сервером и его внутренним сервером будет менее 1 мс, поэтому установление TCP-соединения происходит намного быстрее, чем между клиентом.

Это только половина причины, хотя. HTTP-сервер выделяет определенный объем памяти для каждого клиентского соединения. С Keep-Alive он будет поддерживать соединение активным, и, соответственно, он будет поддерживать определенный объем памяти на сервере до истечения времени ожидания Keep-Alive, которое может достигать 15 с, в зависимости от конфигурации сервера. ,

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

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

ThatGraemeGuy
источник
5
Престижность за отличное объяснение Грэм, я никогда не тратил достаточно времени на столь долгий ответ тем, кто меня об этом спрашивал, и я обязательно
оставлю
2
Будет ли преимущество keepAlive на стороне сервера, если соединение между прокси и бэкэндом было https?
Авмохан
«HTTP-сервер выделяет определенный объем памяти для каждого клиентского подключения», да, но таких подключений будет мало (?) Только одно на балансировщик нагрузки? Не один на одного клиента в Интернете (?)
Raedwald
@Raedwald, если ваш балансировщик нагрузки ограничен созданием одного HTTP-соединения с каждым резервным сервером, у вас будет довольно плохое время. :-)
ThatGraemeGuy
7

Nginx поддерживает поддержку активности с обеих сторон.

VBart
источник
Вы бы сказали, что keep alive полезен для бэкэндов, если между прокси и бэкэндами была задержка? Кроме того, какое оптимальное количество разрешенных соединений будет разрешено?
CMCDragonkai
@CMCDragonkai Если ваши серверные части расположены на выделенных серверах, может быть полезно избежать задержки подключения, которая зависит от вашей сети. Там нет золотой середины, оптимальное число в основном зависит от вашей настройки, вашей среды, вашего приложения и шаблона запроса.
VBart
Я надеюсь найти уравнение, чтобы решить это!
CMCDragonkai
2
Вопрос, который я прочитал, заключается не в том, поддерживает ли nginx keep-alive в восходящем потоке, а в том, поддерживает ли nginx отключение keep-alive на восходящем.
user45793