PassFront
  1. PassFront
  2. База знаний
  3. HTTP и HTTPS

Что такое keep-alive, пул соединений и head-of-line blocking?

HTTP и HTTPS

Keep-alive переиспользует одно TCP-соединение для многих запросов, пул держит набор таких соединений наготове, а head-of-line blocking — ситуация, когда застрявший первый элемент очереди задерживает всех за ним.

Keep-alive

  • В HTTP/1.1 соединение постоянное по умолчанию, закрывает его Connection: close. Экономятся TCP и TLS handshake и разогретое окно перегрузки.
  • Сервер закрывает простаивающие соединения по таймауту: в nginx keepalive_timeout по умолчанию 75 с.
  • Классическая ошибка: клиент держит соединение дольше, чем сервер или балансировщик, пишет в закрытый сокет и получает ECONNRESET.

Пул соединений

  • HTTP/1.1 обслуживает один запрос за раз на соединение, поэтому браузер открывает до 6 соединений на хост.
  • В бэкенде пул ограничивает параллелизм к апстриму и защищает от исчерпания эфемерных портов.
// пул у браузера: ≤ 6 сокетов на хост в HTTP/1.1
await Promise.all([...Array(10)].map((_, i) => fetch(`/api/${i}`).then((r) => r.text())));
for (const e of performance.getEntriesByType('resource'))
  console.log(e.nextHopProtocol, e.connectStart === e.connectEnd ? 'из пула' : 'новое');
document.head.append(Object.assign(document.createElement('link'),
  { rel: 'preconnect', href: 'https://api.example.com' })); // прогрев DNS+TCP+TLS

Head-of-line blocking

  • HTTP-уровень: в HTTP/1.1 ответы идут строго по порядку, pipelining не прижился именно поэтому. HTTP/2 мультиплексирует потоки в одном соединении.
  • TCP-уровень: потеря одного пакета стопорит все потоки HTTP/2 до ретрансмита. QUIC в HTTP/3 держит потоки независимыми.

Коротко для собеседования

Переиспользование соединений экономит рукопожатия, а пул ещё и ограничивает нагрузку на апстрим. Типичная ошибка — клиентский таймаут простоя длиннее серверного, отсюда ECONNRESET; а при сильных потерях одно соединение HTTP/2 может проиграть шести соединениям HTTP/1.1.

Другие вопросы раздела