Keepalive существует в двух контекстах, которые важно различать: HTTP Keep-Alive (постоянные соединения) и TCP Keepalive (обнаружение разорванных соединений). Оба механизма используются на сервере для оптимизации производительности и надёжности.
HTTP Keep-Alive (постоянные соединения)
В HTTP/1.0 каждый запрос требовал отдельного TCP-соединения: установка (3-way handshake) — запрос — ответ — закрытие. На странице с 50 ресурсами (CSS, JS, images) это 50 соединений.
HTTP Keep-Alive (HTTP/1.1, RFC 2616) позволяет повторно использовать TCP-соединение для нескольких запросов. Клиент отправляет заголовок Connection: keep-alive, сервер соглашается и держит соединение открытым. В HTTP/2 и HTTP/3 keepalive не нужен — один поток мультиплексирует все запросы.
Настройка в Nginx:
keepalive_timeout 65;— время ожидания следующего запроса (сек). Значение 0 отключает keepalive.keepalive_requests 1000;— максимум запросов в одном соединении (Nginx 1.19.10+, было 100 по умолчанию).keepalive_time 1h;— максимальное время жизни соединения (Nginx 1.19.10+).
Для upstream-соединений (Nginx <-> PHP-FPM, Nginx <-> Node.js): keepalive 32; в блоке upstream — держать 32 idle-соединения к upstream постоянно.
TCP Keepalive
TCP Keepalive — механизм ядра для обнаружения мёртвых соединений. После заданного периода простоя ядро отправляет пустой TCP-пакет (probe). Если ответа нет после N проб — соединение считается разорванным и закрывается.
Параметры Linux (sysctl):
net.ipv4.tcp_keepalive_time = 7200— пауза до первого probe (2 часа по умолчанию).net.ipv4.tcp_keepalive_intvl = 75— интервал между probe (75 сек).net.ipv4.tcp_keepalive_probes = 9— число probe до признания разрыва.
История
HTTP Keep-Alive появился как расширение в HTTP/1.0 (header Connection: keep-alive) и стал стандартом в HTTP/1.1 (RFC 2616, 1999). TCP Keepalive описан в RFC 1122 (Requirements for Internet Hosts, 1989). HTTP/2 (2015) устранил необходимость в HTTP Keep-Alive через мультиплексирование потоков.
На что обращать внимание
Слишком высокий keepalive_timeout в Nginx при большом числе клиентов приводит к исчерпанию файловых дескрипторов (проверяйте worker_rlimit_nofile и ulimit -n). Для HAProxy keepalive критичен при балансировке: без него каждый запрос создаёт новое соединение к backend. В пулах соединений к БД (pgBouncer, ProxySQL) TCP keepalive необходим для обнаружения мёртвых соединений через NAT.
История Keepalive в HTTP
HTTP Persistent Connections (keep-alive) предложены в HTTP/1.0 через заголовок Connection: Keep-Alive. В HTTP/1.1 (RFC 2616, 1999) persistent connection стал поведением по умолчанию. HTTP/2 (RFC 7540, 2015) использует мультиплексирование — несколько запросов в одном TCP-соединении. TCP keepalive — отдельный механизм ядра ОС для обнаружения мёртвых соединений (RFC 1122, 1989). Nginx поддерживает upstream keepalive с версии 1.1.4 (2011) — переиспользование соединений к PHP-FPM/backends.
Keepalive в Nginx для хостинга
# HTTP Keepalive для клиентов
keepalive_timeout 65; # держать соединение 65 сек
keepalive_requests 1000; # максимум запросов на соединение
# Upstream keepalive к PHP-FPM
upstream php_backend {
server 127.0.0.1:9000;
keepalive 32; # пул из 32 keepalive-соединений
}
location ~ \.php$ {
fastcgi_pass php_backend;
fastcgi_keep_conn on;
}
TCP Keepalive vs HTTP Keepalive
| Параметр | TCP Keepalive | HTTP Keepalive |
|---|---|---|
| Уровень | L4 (Transport) | L7 (Application) |
| Цель | обнаружение мёртвых соединений | переиспользование TCP-соединения |
| Настройка Linux | sysctl net.ipv4.tcp_keepalive_* | nginx keepalive_timeout |
| Проблема | занятые слоты сокетов | слишком много idle-соединений |
Типичные ошибки
- Слишком долгий keepalive_timeout на нагруженном VPS: исчерпание дескрипторов файлов (
Too many open files). - Отключённый HTTP/2: без него каждый ресурс требует отдельного TCP-соединения.
- Upstream keepalive без
fastcgi_keep_conn on— директива keepalive не работает для FastCGI.