...

HTTP Keep-Alive Timeout: оптимальная конфигурация для производительности сервера

В центре внимания HTTP Keep-Alive Timeout Я покажу вам, как установить время простоя, чтобы соединения использовались повторно, не блокируя потоки. Я объясню конкретные значения, покажу типичные подводные камни и предоставлю проверенные и испытанные конфигурации для nginx, Apache и операционная система.

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

  • Баланс: Слишком короткие увеличивают количество рукопожатий, слишком длинные блокируют потоки.
  • ЗначенияВ основном 5-15 с и 100-500 запросов на одно соединение.
  • КоординацияСогласование тайм-аутов клиента, LB и брандмауэра.
  • Особые случаиWebSockets, SSE, длинный опрос отдельно.
  • Мониторинг: Мониторинг открытых сокетов, FD и задержек.

Краткое объяснение HTTP Keep-Alive

Я держу TCP-соединения с Keep-Alive открыты таким образом, что несколько запросов используют одну и ту же линию. Это позволяет избежать повторных рукопожатий TCP и TLS и уменьшить CPU-заметно увеличивает объем работы. Это особенно полезно для множества небольших файлов, таких как иконки, JSON или CSS. Каждое новое соединение, которого удается избежать, уменьшает количество переключений контекста и разгружает рутины ядра. В бенчмарках с высокой долей GET общая продолжительность значительно сокращается, поскольку генерируется меньше пакетов SYN/ACK и больше вычислительного времени перетекает в логику приложения.

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

Понимание правильного тайм-аута

Таймаут определяет, как долго неактивное соединение остается открытым, прежде чем сервер закроет его. закрывает. Если я установлю слишком короткое время, клиенты будут постоянно открывать новые TCP-соединения, что Накладные повышается. Если я установлю слишком большой срок, простаивающие соединения припаркуют ценные рабочие или потоки. Искусство заключается в балансе между повторным использованием и потреблением ресурсов. Я тестирую на практике: сначала устанавливаю его приблизительно, а затем точно настраиваю с помощью нагрузочных тестов.

Я также обращаю внимание на соотношение между временем отклика и окнами простоя. Если типичное взаимодействие пользователя между двумя нажатиями составляет 2-4 секунды, то таймаут в 5-15 секунд обычно покрывает реальную картину. Короткие вызовы API могут легко выдержать 5-10 секунд, мультимедийные нагрузки - 10-15 секунд. Важно, чтобы я не преувеличивал: слишком длинные таймауты редко приводят к более Пропускная способность, но часто приводят к блокировке Ресурсы. Я быстро узнаю об этом по растущему числу открытых розеток и высоким показателям FD.

Чистое разделение типов тайм-аутов

Я строго различаю Таймаут простоя (Keep-Alive), Таймаут чтения/заголовка (сколько времени сервер ожидает входящих запросов) и Таймаут отправки/записи (как долго терпима отправка в сторону клиента). Эти категории выполняют разные задачи:

  • Таймаут простоя: Контролирует повторное использование и продолжительность парковки неактивных соединений.
  • Таймаут чтения/заголовка: Защищает от медленных клиентов (медленных лорисов) и полуотправленных заголовков.
  • Таймаут отправки/записи: Предотвращает бесконечное ожидание сервером медленного приема на клиенте.

На сайте nginx Я намеренно использую header_timeout/read_timeout и send_timeout для контекста (http/server/location) в дополнение к keepalive_timeout. В новых версиях я опционально устанавливаю время_перехвата, чтобы ограничить максимальное время жизни соединения, даже если оно остается активным. В Apache Я также использую RequestReadTimeout (mod_reqtimeout) и проверьте Тайм-аут (глобальный) отдельно от KeepAliveTimeout. Такое разделение - важный элемент, препятствующий перераспределению ресурсов без реальной пользы.

Рекомендуемые значения на практике

Для продуктивных сред я устанавливаю таймаут ожидания 5-15 секунд и 100-500 запросов на соединение. В этом диапазоне достигается хороший показатель повторного использования соединений и снижается количество неработающих соединений. На сайте nginx Я использую keepalive_timeout 10s в качестве начального значения и keepalive_requests 200. Если трафик большой, я умеренно увеличиваю его, если вижу слишком много новых TCP-соединений. Если трафик редкий, я снова снижаю значение, чтобы предотвратить наплыв неработающего трафика.

Тем, кто углубляется, будет полезен четкий процесс настройки с точками измерения. Для этого я обобщил свои рекомендации в практическом руководстве, которое описывает путь от измерения к настройке и управлению. Для быстрого начала я рекомендую вам ознакомиться с моими шагами в Настройка Keep-Alive. Как управлять Повторное использование и ограничений и избежать неожиданностей. В конечном итоге важна низкая задержка и стабильность Пропускная способность.

Риски, связанные с длительными тайм-аутами

Длительный тайм-аут сохраняет соединения искусственными открыть и блокирует рабочих, даже если запроса не последовало. Это приводит к разбуханию сокетов и увеличению числа файловых дескрипторов. Если процесс достигает своего предела, я вижу ошибки отклонения приема или очереди при установлении соединения. Память растет, сборщики или распределители мусора требуют дополнительного времени, а задержки увеличиваются. В случае ошибки клиенты отправляют сообщения на уже закрытые сокеты и получают криптографические сообщения Ошибка.

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

Конфигурация: nginx, Apache и уровень ОС

Я начинаю с уровня веб-сервера и устанавливаю таймаут и ограничения. На nginx Я устанавливаю keepalive_timeout 5-15 с и keepalive_requests 100-500. В Apache с event-MPM я комбинирую KeepAlive On, KeepAliveTimeout 5-15 и MaxKeepAliveRequests 100-500. Затем я калибрую пулы рабочих или потоков в соответствии с ожидаемой нагрузкой. Это предотвращает превращение неработающих keep-alives в продуктивные. Слоты Связка.

Я увеличиваю лимиты и очереди на уровне операционной системы. Я устанавливаю ulimit -n по крайней мере на 100 000, настраиваю net.core.somaxconn и tcp_max_syn_backlog и проверяю обработку TIME_WAIT. Это гарантирует, что ядро и процесс имеют достаточно Ресурсы обеспечить. Наконец, я проверяю пути от сетевой карты через балансировку IRQ к приложению. Это позволяет мне своевременно выявлять узкие места и поддерживать Латентность низкий.

Компонент Директива/установка Рекомендация Подсказка
nginx keepalive_timeout 5–15 с Короче при небольшом трафике, дольше при большом количестве небольших запросов
nginx keepalive_requests 100–500 Перерабатывает соединения и уменьшает Утечки
Апач (событие) KeepAliveTimeout 5–15 с Event-MPM управляет простоями более эффективно, чем prefork
Операционная система ulimit -n ≥ 100.000 Больше открытых FD для многих Розетки
Операционная система net.core.somaxconn Увеличить Меньше отклоненных соединений под Пиковая нагрузка

Обратный прокси и повторное использование восходящего потока

Я всегда думаю, что keep-alive из конца в конец. За пограничным сервером часто располагается цепочка обратных прокси → серверы приложений. Для nginx я активирую свой собственный Бассейны Keep Alive (upstream keepalive, keepalive_requests, keepalive_timeout), установите proxy_http_version 1.1 и удалите „Connection: close“. Это также избавляет меня от внутренний рукопожатия и разгрузить бэкенды приложений (Node.js, Java, PHP-FPM). В Apache с mod_proxy я также сохраняю постоянные соединения с внутренними серверами и ограничиваю их количество для каждого направления, чтобы одна точка не монополизировала пулы.

Я измеряю отдельно: коэффициент повторного использования Клиент→Конец и Конец→Бэкенд. Если я вижу хорошее повторное использование на границе, но много новых подключений к бэкенду, я выборочно увеличиваю пулы восходящего потока. Это позволяет мне масштабироваться без глобального увеличения таймаутов фронтенда.

Рабочие, потоки и ограничения ОС

Я измеряю рабочие, события и потоки не в соответствии с желаемыми значениями, а в соответствии с профиль нагрузки. Для этого я слежу за активными запросами, простаивающими рабочими, загрузкой цикла событий и переключением контекста. Если потоки простаивают в режиме ожидания, я снижаю таймаут или максимальное время простоя для каждого потока. Если я вижу, что процессор постоянно загружен на 100 %, я проверяю очереди приема, распределение IRQ и сетевой стек. Небольшие исправления лимитов FD и отставаний часто имеют большое значение. Эффекты.

Я планирую запас прочности реалистично. 20-30-процентный резерв в потоках и FD обеспечивает безопасность при пиковых нагрузках. Если я переборщу, то потеряю кэш и увеличится количество отходов. Если я недорабатываю, запросы остаются в очередях или заканчиваются. Правильное пересечение Вместимость и эффективность обеспечивают низкие задержки и защищают Стабильность.

Координируйте тайм-ауты клиентов, балансировщиков нагрузки и брандмауэров.

Я устанавливаю временные ограничения на всем пути, чтобы не было тупиков. Соединения создаются. В идеале клиенты закрываются минимально раньше, чем сервер. Балансировщик нагрузки не должен обрываться короче, иначе я увижу неожиданные перезагрузки. Я включаю значения простоя NAT и брандмауэра, чтобы соединения не терялись на сетевом пути. исчезнуть. Эта настройка предотвращает повторные передачи и сглаживает кривые нагрузки.

Я поддерживаю понятную цепочку с помощью четких схем: клиент → LB → веб-сервер → приложение. Я документирую таймауты простоя, таймауты чтения/записи и стратегии повторных попыток для каждого звена. Если я меняю значение, я проверяю соседей. Это позволяет сохранить последовательность пути и получить воспроизводимые результаты измерений. Такая дисциплина экономит время в Устранение неполадок и увеличивает надежность.

Безопасность: Защита от медлительных лорисов и праздных злоупотреблений

Слишком щедрые тайм-ауты Атакующие поверхности. Поэтому я устанавливаю ограничения, которые позволяют законное повторное использование, но затрудняют злонамеренное открытие. В nginx помогают ограничения на время ожидания заголовков и чтения, размер request_headers_size и жесткий верхний предел для keepalive_requests. В Apache я использую mod_reqtimeout и ограничиваю параллельные соединения на один IP. Ограничения скорости и limit_conn в nginx также защищают от наводнения множества неработающих сокетов. Для долго работающих конечных точек я выделяю отдельные пулы, чтобы атаки на потоки не связывали обычных работников API.

Особые случаи: Long Polling, SSE и WebSockets

Длинные ручьи сталкиваются с короткими Тайм-ауты и нуждаются в собственных правилах. Я технически отделяю эти конечные точки от классических маршрутов API и активов. Для SSE и WebSockets я устанавливаю более высокие таймауты, выделенные пулы рабочих и жесткие ограничения на IP. Я поддерживаю соединение с помощью сердцебиения или пинга/понга и быстро распознаю разрывы. Таким образом, потоки не блокируют потоки для регулярных Короткие запросы.

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

HTTP/2, мультиплексирование и keep-alive

HTTP/2 мультиплексирует несколько потоков через Соединение, но остается зависимым от таймаутов. Я поддерживаю умеренное окно простоя, потому что сессии могут парковаться и под HTTP/2. Высокие keepalive_requests здесь менее важны, но рециркуляция по-прежнему полезна. Блокировка в голове линии переходит на уровень кадра, поэтому я продолжаю измерять задержку на Поток. Если вы хотите провести более глубокое сравнение, вы найдете справочную информацию на Мультиплексирование HTTP/2.

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

TLS, возобновление сеанса и HTTP/3/QUIC

Рукопожатия TLS стоят дорого. Я использую Возобновление сеанса (билеты/идентификаторы) и сшивание OCSP, чтобы быстрее восстанавливать соединение в случае его обрыва. В HTTP/3 QUIC берет на себя транспортный уровень: здесь Таймаут простоя QUIC аналогичен Keep-Alive, но на основе UDP. Здесь я также поддерживаю умеренные окна и измеряю количество ретрансляций, поскольку потери пакетов имеют другой эффект, чем в случае с TCP. Для смешанных сред (H1/H2/H3) я выбираю стандартные эталонные значения и делаю тонкую настройку для каждого протокола.

Мониторинг, метрики и нагрузочные тесты

Я доверяю данным измерений больше, чем интуиции, и начинаю с четкого KPIs. Важными являются: открытые сокеты, использование FD, новые соединения/сек, задержки (P50/P90/P99), количество ошибок и ретрансляций. Я запускаю реалистичные профили нагрузки: разогрев, плато, снижение темпа. Затем я сравниваю кривые до и после изменения таймаута. Взгляд на Очередь серверов помогает четко интерпретировать время ожидания.

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

Методы и инструменты измерения на практике

  • Экспресс-тесты: Я использую такие инструменты, как wrk, ab или vegeta, для проверки квот повторного использования (-H connection: keep-alive vs. close), соединений/с и процентного соотношения задержек.
  • Вид системы: ss/netstat показывает статусы (ESTABLISHED, TIME_WAIT), lsof -p потребление FD, dmesg/syslog указывает на падения.
  • Метрики веб-сервера: nginx stub_status/VTS и Apache mod_status предоставляют данные об активности/простоях/ожиданиях и запросах/. По ним я могу определить пики бездействия или узкие места в работе.
  • Следы: Я использую распределенную трассировку, чтобы отслеживать, где происходит ожидание - на границе сети или в приложении.

Настройка шаг за шагом

Сначала я определяю реальную модель использования: сколько запросов за сессию, какие Интервалы между кликами, насколько велики ответы. Затем я устанавливаю начальный профиль: таймаут 10 с, keepalive_requests 200, умеренное количество рабочих. Затем я провожу нагрузочные тесты с репрезентативными данными. Я оцениваю количество новых соединений в секунду и использование FD. Затем я настраиваю Значения с интервалом в 2-3 секунды.

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

Kubernetes, контейнеры и автомасштабирование

В контейнерных средах я использую conntrack-лимиты, лимиты FD подгрупп и отставания узлов. Я обеспечиваю согласованные таймауты простоя между Ingress, сервисной сеткой/прокси и приложением. Для автоматического масштабирования я обращаю внимание на Время сливаКогда стручки завершаются, они должны отклонять новые соединения через „Connection: close“ и обслуживать существующие без ошибок. Слишком длинные значения keep alive неоправданно удлиняют стоки, а слишком короткие порождают штормы рукопожатий при масштабировании.

Благодатное завершение и скользящее развертывание

Я также планирую отключиться. Перед развертыванием я постепенно уменьшаю Keep-Alive или отправляю целевые запросы. Соединение: закрыто на Responses, чтобы клиенты не открывали новые простаивающие соединения. В nginx таймаут_выключения_работника для выполняющихся запросов. В Apache я использую изящные механизмы и слежу за MaxConnectionsPerChild/Worker, чтобы рециркуляция происходила автоматически с течением времени. Это позволяет поддерживать плавность развертывания без жесткого ограничения открытых сокетов.

Настройка ОС: порты, тайм-ауты, параметры ядра

  • эфемерные порты: Выберите широкий диапазон для ip_local_port_range, чтобы короткие соединения не столкнулись с нехваткой.
  • TIME_WAIT: Я слежу за пиками TW. Современные стеки хорошо справляются с этим; я избегаю сомнительных твиков (tw_recycle).
  • tcp_keepalive_time: Я не путаю его с HTTP Keep-Alive. Это механизм ядра для распознавания мертвых пиров - полезный за NAT, но не заменяющий окно простоя HTTP.
  • Запасные части и буферы: Измерьте somaxconn, tcp_max_syn_backlog и rmem/wmem разумно, чтобы не дросселировать под нагрузкой.

Контрольный список по устранению неполадок

  • Много новых соединений/, несмотря на keep-alive: Слишком короткий тайм-аут или клиенты/ББ отключились раньше времени.
  • Высокие показатели холостого хода и полное FD: Слишком длительный тайм-аут или слишком большой пул рабочих для схемы трафика.
  • Ошибка RST/Timeout для длительных сессий: NAT/брандмауэр простаивает на слишком коротком пути, асимметрия между каналами.
  • Длинные хвостовые задержки (P99): Проверьте таймауты отправки/чтения, медленные клиенты или переполненные бэки.
  • Бэкенды перегружены, несмотря на низкую краевую нагрузку: Клетка верхнего течения отсутствует или слишком мала.

Профили практики и начальные значения

  • API-first (короткие вызовы): Keep-Alive 5-10 с, keepalive_requests 200-300, жесткие таймауты на чтение заголовков.
  • Электронная коммерция (смешанная): 8-12 с, 200-400, чуть более щедрые для изображений товаров и кэширования просмотров.
  • Активы/CDN-подобные (много маленьких файлов): 10-15 с, 300-500, сильные водоемы в верхнем течении и высокие пределы FD.
  • Интранет/низкая нагрузка: 5-8 с, 100-200, чтобы холостой ход не был доминирующим.

Краткое резюме

Я установил таймаут HTTP keep-alive, чтобы соединения использовались повторно без блокировки потоков. На практике 5-15 секунд и 100-500 запросов на соединение дают очень хорошие результаты. Я координирую таймауты клиентов, балансировщиков нагрузки и брандмауэров, разделяю длительные соединения, такие как WebSockets, и регулирую ограничения ОС. С помощью чистого мониторинга, реалистичных нагрузочных тестов и небольших шагов я добиваюсь низких показателей Задержки и высокий Пропускная способность. Те, кто придерживается этой дисциплины, получают ощутимую производительность от имеющегося оборудования.

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

Хостинг-сервер для потокового вещания с высокой пропускной способностью и низкой задержкой
Серверы и виртуальные машины

Хостинг для потоковых приложений: Оптимизация пропускной способности и задержки

Хостинг для потоковых приложений: Оптимальная пропускная способность и задержка для потоков 4K. Советы, таблицы и тест победителя webhoster.de.

Сервер оптимизирован с учетом ограничений дескрипторов файлов в хостинге
Серверы и виртуальные машины

Сервер лимитов дескрипторов файлов: Оптимизация лимитов в хостинге

Оптимизируйте лимит файлового дескриптора сервера: Избегайте истощения fd с помощью настройки хостинга для стабильной работы веб-серверов и максимальной производительности.