...

Оптимизация запросов Keepalive в NGINX: максимальная производительность веб-сервера за счет целенаправленной настройки

С nginx keepalive Я снижаю затраты на установку соединения, сокращаю количество обменных сеансов и заметно сокращаю время отклика. Тщательно настроенные таймауты, ограничения на количество запросов для каждого соединения и повторное использование сокетов верхнего уровня обеспечивают ощутимое повышение производительности без необходимости приобретения нового оборудования.

Центральные пункты

  • Тайм-ауты Выбирайте разумно: время простоя должно быть настолько коротким, насколько это необходимо, и настолько длинным, насколько это полезно.
  • Запросы Ограничение на одно соединение: стабильная работа сокетов, отсутствие зависаний.
  • Пул-серверы Upstream Включить: постоянные соединения с бэкендом для каждого рабочего процесса.
  • Рабочий и настроить соединения: достаточное количество слотов для неактивных и активных клиентов.
  • Мониторинг Настроить: отслеживать скорость соединения, задержку и количество ошибок.

NGINX Keepalive: эффективность и затраты

Я намеренно оставляю TCP-соединения открытыми, потому что Рукопожатия стоят дороже и доминируют при большом количестве мелких запросов. Постоянные сокеты не только сокращают время RTT, но и выравнивают нагрузку на ЦП, поскольку криптографические операции для TLS запускаются реже. Однако каждое открытое соединение занимает Ресурсы, например, файловые дескрипторы и буферы, за которыми нужно следить. Все дело в балансе: достаточное количество повторного использования для обеспечения скорости и достаточный ресурс для установления новых соединений в моменты пиковой нагрузки. Тот, кто найдет этот баланс, сможет добиться стабильно низких показателей TTFB и обеспечить пользователям ощущение высокой скорости работы.

HTTP/2 и HTTP/3: мультиплексирование в сочетании с Keepalive

С HTTP/2 и HTTP/3 количество необходимых соединений на одного клиента уменьшается, поскольку по одной линии проходят несколько потоков. Тем не менее функция Keepalive по-прежнему остается актуальной: одно соединение должно надежно оставаться открытым, иначе преимущество мультиплексирования теряется из-за частых повторных подключений.

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

http {
    # HTTP/2: таймаут простоя для неиспользуемых, но открытых потоков
    http2_idle_timeout 60s;

    # HTTP/3/QUIC: аналогичная логика для соединений на основе UDP
    http3_idle_timeout 60s;

    # Возобновление TLS снижает затраты на установку соединения при повторном подключении
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
}

Мультиплексирование снижает необходимое количество параллельных соединений TCP/QUIC, но не уменьшает важность правильные таймауты. Тем, кто использует HTTP/2/3, часто можно установить более длительные таймауты на стороне клиента, поскольку множество небольших ресурсов передается по одному и тому же каналу. Важно: сохранять возможность измерения Время до первого байта, показатели ошибок и открытые потоки для каждого соединения.

Правильная настройка параметра Client-Keepalive

Для браузерных клиентов я управляю повторным использованием с помощью keepalive_timeout и keepalive_requests, чтобы сокеты просуществовали достаточно долго, но при этом не блокировались бесконечно. В качестве отправной точки я использую таймаут 30–60 секунд и 100–300 запросов на каждое соединение, а затем корректирую эти значения с учетом показателей. Подробную классификацию можно найти в этом Руководство по таймауту keepalive, в котором объясняется их влияние на задержку и ресурсы сервера. Более короткие таймауты подходят для очень большого количества коротких запросов, а более длительные — для периодических обращений к API. Для начала я устанавливаю четкие значения по умолчанию и измеряю их влияние на количество открытых соединений, а также на статистику ошибок.

http {
    # Неактивные соединения с клиентом
    keepalive_timeout 60s;
    # Максимальное количество запросов на одно TCP-соединение
    keepalive_requests 200;

    # Дополнительно: отключение Keep-Alive для определённых клиентов (устаревшие ошибки)
    # keepalive_disable msie6;
}

Функция Upstream-Keepalive в обратном прокси-сервере

Между NGINX и бэкенд-приложениями я использую постоянные сокеты upstream, поскольку подключение к PHP-FPM, Node.js или сервисам на Python также Латентность стоит. Для этого я активирую в пуле Upstream соответствующее количество многоразовых соединений на каждого рабочего процесса. Важно использовать HTTP/1.1 в направлении сервера и пустой заголовок Connection, иначе запрос клиента „close“ нарушит персистентность бэкэнда. Я ориентируюсь на количество одновременных запросов и настраиваю пул таким образом, чтобы новых подключений практически не возникало. Таким образом, время подключения к бэкенду сокращается, и вся цепотка работает быстрее Ответы.

upstream backend {
    server 127.0.0.1:9000;
    keepalive 64; # — количество постоянных соединений с upstream-сервером на каждый рабочий процесс
}

server {
    location / {
 proxy_pass http://backend;
        proxy_http_version 1.1;
 proxy_set_header Connection "";
 # TCP-Keepalive для сокетов upstream на уровне ОС
 proxy_socket_keepalive on;
    }
}

Расчет размеров пула и бюджет соединений

Я рассчитываю пулы с учетом реальных условий: количество постоянных соединений с источником определяется worker_processes × keepalive на каждый Upstream. Если использовать 8 рабочих процессов и параметр keepalive равный 64, то на каждый экземпляр будет открыто до 512 сокетов на каждый Upstream. При работе за балансировщиком нагрузки или при наличии нескольких целей Upstream это количество может быстро увеличиться.

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

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

Точная настройка: таймауты и ограничения на количество запросов

Я комбинирую таймаут и ограничение количества запросов таким образом, чтобы соединения эффективно использовались повторно, не приводя к Беговой лыжник . Высокие значения по обеим осям сводят к минимуму количество соединений, но повышают риск зависания сокетов при сбоях в сети. Низкие значения обеспечивают свежие соединения, но требуют дополнительных рукопожатий. Я продвигаюсь небольшими шагами, наблюдаю за ошибками и корректирую настройки через определенные промежутки времени. В приведенной ниже таблице показаны целесообразные диапазоны начальных значений для различных моделей использования и представлена краткая Ориентация.

Сценарий keepalive_timeout keepalive_requests Подсказка
Много кратковременных посещений страниц 10–30 с 100-300 Быстрая повторная загрузка, низкая загрузка в режиме ожидания
Типичный веб-сайт 60–120 с 200–400 Хороший средний показатель для Assets и HTML
API с периодическими вызовами 60–120 с 300–1000 Более высокий показатель повторного использования для клиентов
Внутренние службы / шлюзы 30–90 секунд 500–1000+ Стабильность важнее минимального количества подключений

Настройка рабочих процессов и соединения

Я поставил рабочие_процессы установить значение «auto» или указать количество ядер процессора и предусмотреть достаточный запас рабочие_соединения , поскольку неактивные сокеты занимают слоты. Слишком низкие ограничения препятствуют приему новых соединений, даже если ресурсы ЦП ещё доступны. Тем, кто использует большие пулы Keepalive, требуется достаточное количество дескрипторов и слотов событий на каждый рабочий процесс. Хорошее введение в эту тему даёт „Масштабирование Worker-Connections“, в которой объясняются взаимосвязи между событиями, соединениями и нагрузкой. Тщательно продуманные настройки позволяют одновременно использовать повторное использование в режиме ожидания и создание новых соединений.

worker_processes auto;

events {
    worker_connections 4096;
    # Опционально: параметр reuseport может улучшить распределение на уровне ядра
    # multi_accept on;
}

http {
    keepalive_timeout 60s;
    keepalive_requests 200;

 upstream backend {
 server 127.0.0.1:9000;
 keepalive 64;
    }
}

Настройка операционной системы и сокетов

Я проверяю системные ограничения, чтобы функция Keepalive могла раскрыть весь свой потенциал. Недостаточное количество дескрипторов или переполненные очереди сокетов приводят к искусственные ограничения. Помимо ulimit и worker_rlimit_nofile, решающую роль играют ограничения ядра.

# Примерные значения sysctl (настраивайте с осторожностью и после тестирования)
fs.file-max = 1000000
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 16384
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_syn_backlog = 262144

Я настраиваю эти параметры с учетом условий эксплуатации: для многих кратковременных соединений выгодно использовать более широкий диапазон портов и короткие интервалы FIN/TIME_WAIT. При использовании Upstream-Keepalive я уменьшаю Neuconnects, благодаря чему нагрузка в режиме TIME_WAIT уменьшается. Кроме того, я учитываю NAT-Устройства между прокси и бэкендом: слишком агрессивные таймауты простоя в сети приводят к непредсказуемому обрыву соединений. Умеренное ограничение количества запросов на сокет и использование TCP-Keepalive (proxy_socket_keepalive on;) предотвращают „застоявшиеся“ связи.

Правильно установить заголовок и версию HTTP

Я обращаю внимание на HTTP/1.1 в бэкенд, поскольку Upstream-Keepalive работает только с ним. Кроме того, я отключаю управление активными соединениями через заголовки, чтобы NGINX самостоятельно управлял сохранением соединений. На стороне клиента я настраиваю Keep-Alive в соответствии со стандартом и ограничиваю время жизни с помощью таймаута и ограничения количества запросов. Кроме того, я проверяю таймауты простоя бэкэнда и устанавливаю их на минимально более высокое значение, чем в NGINX, чтобы избежать ошибок сброса. Чистые заголовки обеспечивают Повторное использование без нежелательных закрытий.

Пример #: прокси-локация с правильными заголовками
location /api/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}

Различие: HTTP Keep-Alive и TCP-Keepalive

Я провожу строгое различие между HTTP Keep-Alive (несколько HTTP-запросов на одно соединение) и TCP-Keepalive (Проверки на уровне ОС для обнаружения неработающих удаленных узлов). Функцию HTTP Keep-Alive я настраиваю с помощью keepalive_timeout и keepalive_requests, тогда как TCP-Keepalive, в зависимости от стека, могут составлять proxy_socket_keepalive on; и системные параметры. Для бэкендов, работающих через нестабильные сети, я включаю TCP-keepalives, чтобы быстрее очищать зависшие сокеты.

Длительные соединения и особые случаи: WebSockets, SSE, gRPC

WebSockets и события, отправляемые сервером, являются Беговой лыжник, которые поддерживают соединение в течение длительного времени — здесь классический алгоритм Reuse играет второстепенную роль. Я обеспечиваю подходящие proxy_read_timeout и защити меня с помощью send_timeout против Слоулорис-эффекты. В случае gRPC (на основе HTTP/2) необходимо учитывать особенности мультиплексирования; таймауты простоя я настраиваю таким образом, чтобы потоки не закрывались без необходимости.

location /ws/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 300s;
    send_timeout 30s;
}

Мониторинг и метрики

Я оцениваю успех по таким показателям, как доля новых подключений в сегменте Upstream, upstream_connect_time и долю открытых соединений на каждого рабочего процесса. Снижение показателей подключений при неизменном или растущем количестве запросов свидетельствует об успешном повторном использовании соединений. Заметные таймауты или сбросы соединений указывают на несогласованность таймаутов между NGINX и бэкэндом. Кроме того, я отслеживаю состояние памяти, файловых дескрипторов и очередей событий под нагрузкой. Регулярный мониторинг позволяет своевременно выявлять тенденции и предотвращать дорогостоящие Неудачи.

Улучшения в ведении журналов для обеспечения прозрачности повторного использования

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

log_format keepalive_fmt
  '$remote_addr $host "$request" $status $body_bytes_sent '
  '$request_time $upstream_connect_time '
  'conn:$connection reqs:$connection_requests';

access_log /var/log/nginx/access_keepalive.log keepalive_fmt;

Я отслеживаю медианные значения и значения P95/P99 upstream_connect_time а также распределение $ запросы на подключение. Увеличение количества повторных попыток при стабильной задержке означает, что пулы и таймауты выбраны правильно.

Типичные камни преткновения и решения

Слишком большие пулы занимают слоты соединений, в то время как новые клиенты остаются в ожидании, поэтому я поддерживаю умеренный размер пулов и контролирую их. Различные таймауты простоя между прокси и бэкендом приводят к сбросам, поэтому я устанавливаю значение для бэкенда чуть выше, чем NGINX. Забытое значение „Connection: close“ в заголовке прокси прерывает персистентность, поэтому я всегда очищаю этот заголовок. Переговоры TLS при большом количестве новых подключений могут создавать нагрузку на ЦП, которую я снижаю за счет увеличения доли повторного использования. При спорадических сбоях в сети помогает умеренное ограничение количества запросов на сокет, чтобы старые Сессии не жить вечно.

Практические конфигурации

Для сайтов с высокой посещаемостью я выбираю короткий таймаут и умеренно высокий лимит запросов, чтобы ресурсы работали эффективно. Для API с повторяющимися вызовами я повышаю лимит, чтобы ещё больше сократить время установления соединения по протоколам TCP и TLS. Я рассчитываю размер пулов upstream с учётом ожидаемой параллельности и тестирую их с использованием реалистичного трафика. Каждая среда ведёт себя по-своему, поэтому после внесения изменений я проверяю задержку и статистику ошибок. Два примера показывают начальные значения, которые я затем уточняю с помощью метрик.

# Сценарий 1: Сайт с высокой посещаемостью
http {
    keepalive_timeout 30s;
    keepalive_requests 300;

 upstream app {
 server 127.0.0.1:8080;
        keepalive 32;
    }

 server {
 listen 443 ssl http2;
 Контроль простоя HTTP/2 (#)
 http2_idle_timeout 45s;
    }
}
# Сценарий 2: API с периодическими вызовами
http {
    keepalive_timeout 75s;
    keepalive_requests 1000;

    upstream api_backend {
 server 127.0.0.1:9001;
 keepalive 64;
    }

    server {
 listen 443 ssl http2;
 # Немного более длительное окно простоя для повторяющихся вызовов
 http2_idle_timeout 75s;
    }
}

Контрольный список для итеративной оптимизации

Я начну с анализа текущей ситуации: характер трафика, время отклика и уровень ошибок задают тон. Затем я устанавливаю таймаут клиента и ограничение на количество запросов на надежные начальные значения и активирую пулы верхнего уровня. Таймауты простоя бэкенда я устанавливаю немного выше, чем в NGINX, чтобы избежать неожиданных сбросы возникают. Затем я отслеживаю скорость установления соединений, время соединения и количество открытых сокетов на каждого рабочего процесса. Те, кто хочет глубже изучить степень повторного использования, найдут полезные материалы по теме Повторное использование соединения и разумные предельные значения.

Дополнительная диагностика: несоответствия и временные характеристики

Если соединение обрывается, казалось бы, „без причины“, я ищу Несоответствия в цепочке: простоя клиента vs. таймаут NGINX vs. простоя бэкенда и промежуточные NAT/шлюзы. Я немного увеличиваю таймаут бэкенда по сравнению со значением NGINX, проверяю коды сброса в журнале ошибок и наблюдаю, не upstream_connect_time показывает пики. Часто при таймауте бэкэнда достаточно небольшого запаса (например, +10–20%), чтобы исключить сбросы.

Кроме того, я обращаю внимание на „затянутый финал“-Фазы: при закрытии NGINX на короткое время пропускает входящие данные, что занимает ресурсы рабочих процессов. Очень большое количество одновременных закрытий может заблокировать события. В таких случаях я настраиваю временные окна закрытия и поддерживаю общее количество открытых соединений на оптимальном уровне с помощью разумных значений Keepalive».

Резюме: Keepalive как средство повышения производительности

Я целенаправленно использую Keepalive, поскольку это снижает затраты на установку соединения, уменьшает задержку и снижает нагрузку на ЦП. Сочетание подходящего таймаута, четко установленного лимита запросов и подходящих пулов upstream приносит ощутимый Скорость. Без мониторинга потенциал остаётся нереализованным, поэтому я постоянно анализирую показатели и постепенно корректирую значения. Тем, кому нужны дополнительные резервы, следует обратить внимание на количество рабочих процессов, слоты соединений и правильную обработку заголовков. Профессиональные настройки, например, в случае веб-сайт webhoster.de, максимально эффективно используют эти возможности и предоставляют быстрые и надежные услуги.

Текущие статьи

Визуализация потоков Page Cleaner MariaDB в современном центре обработки данных
Базы данных

Понимание потоков очистки страниц в MariaDB: как они влияют на производительность

Объяснение принципа работы потоков очистки страниц в MariaDB: механизм очистки страниц в InnoDB MariaDB влияет на количество «грязных» страниц и производительность базы данных.

Веб-сервер NGINX с оптимизированными соединениями Keepalive в современном центре обработки данных
Веб-сервер Plesk

Оптимизация запросов Keepalive в NGINX: максимальная производительность веб-сервера за счет целенаправленной настройки

Узнайте, как оптимизировать запросы Keepalive в NGINX, чтобы значительно повысить производительность вашего веб-сервера. С помощью практических настроек для keepalive_timeout, keepalive_requests, Upstream-Keepalive и настройки рабочих процессов — с особым акцентом на Keepalive в NGINX как ключевой параметр.

Безопасность серверов CloudLinux с защитой от символических ссылок
Безопасность

CloudLinux SecureLinks: защита от атак через символьные ссылки на виртуальном хостинге

CloudLinux SecureLinks защищает хостинг-серверы от атак через символьные ссылки на уровне ядра и повышает уровень безопасности в условиях виртуального хостинга.