HTTP Keep-Alive

Переиспользование одного TCP-соединения для нескольких HTTP-запросов. Сокеты не 1:1 к запросам — экономия handshake и слотов.

Что это

В HTTP/1.0 каждый запрос открывал новый TCP-сокет: handshake → запрос → ответ → close. Это дорого. HTTP/1.1 ввёл Connection: keep-alive (по умолчанию): сокет остаётся открытым после ответа, в нём можно отправить следующий запрос.

В HTTP/2 идёт ещё дальше — мультиплексирование стримов в одном TCP-соединении.

Заголовки

Connection: keep-alive
Keep-Alive: timeout=5, max=1000
  • timeout — сколько сервер держит сокет без активности.
  • max — максимальное число запросов в одном сокете.

API / Пример (Node.js)

const http = require('http');

// Клиент — переиспользует сокеты
const agent = new http.Agent({
  keepAlive: true,
  keepAliveMsecs: 30_000,  // как часто слать TCP keep-alive
  maxSockets: 100,         // лимит сокетов на host
  maxFreeSockets: 10,      // лимит свободных в пуле
});

const req = http.request({ host: 'api.example.com', agent }, (res) => { /* ... */ });

// Сервер
const server = http.createServer((req, res) => res.end('ok'));
server.keepAliveTimeout = 5_000;
server.headersTimeout = 6_000;  // должен быть > keepAliveTimeout

Производительность / Подводные камни

  • Сокеты не 1:1 к запросам — браузеры держат пул на домен (6-8 сокетов в HTTP/1.1).
  • Браузеры игнорируют RFC — открывают новые сокеты ради параллелизма, не дожидаясь reuse.
  • На один пользователь ~100-200 сокетов при долгой сессии.
  • Утечки сокетов в keep-alive — старые баги ноды; нужно правильно навешивать timeout на finish-event.
  • Хип не успевает освобождаться при потоке коротких запросов.
  • headersTimeout > keepAliveTimeout — иначе nginx/balancer закрывает сокет в момент чтения заголовков.
  • HTTP/2 vs Keep-Alive HTTP/1.1 — h2 мультиплексирует на уровне фреймов, h1 — sequential.

🎓 Источники

  • 🎓 2015 Archive — How to Fix a NodeJS Error and Double Performance · 2020-01-02

    • Тезисы: утечка сокетов в keep-alive ноды; тесты без keep-alive обманывают; сокеты не 1:1 к запросам; браузеры открывают 100-200 сокетов на пользователя; патч в 12 строк дал двукратный рост производительности; на finish снять listeners, навесить keep-alive timeout; ни один браузер не следует RFC полностью.
    • Цитата: «Сокеты не 1:1 к запросам. Браузеры открывают 100-200 сокетов на одного пользователя.»
  • 🎓 Летняя школа 2022 созвон #15 — http2 в metacom · 2022-08-12

    • Тезисы: HTTP/2 пишем в стрим (h2 stream), не в сокет; общий файл http-constants для номеров; transform-стрим для экранирования спецсимволов SMTP (. в начале строки → ..).

См. также