Оптимизация тайм-аутов и лимитов соединений: как устранить статус «Недоступно» при высоких нагрузках

Статус «Недоступно» при пиковых нагрузках в 80% случаев вызван не отсутствием ресурсов CPU/RAM, а исчерпанием лимитов TCP-соединений и некорректными тайм-аутами. Когда очередь запросов превышает порог в 128-512 соединений (стандартный listen backlog), сервер начинает отбрасывать пакеты, создавая иллюзию падения системы.

Проблема TCP Backlog и очереди соединений

Многие администраторы увеличивают RAM, игнорируя параметр net.core.somaxconn. По умолчанию в Linux он часто ограничен 128 или 4096. При всплеске трафика (например, рассылка или рекламный запуск), когда входящий поток превышает 500 RPS, очередь переполняется за доли секунды. Это приводит к тому, что клиент получает Connection Refused или бесконечный «зависший» статус, хотя CPU загружен всего на 15-20%.

Кейс: для e-commerce проекта с пиком 2000 RPS увеличение somaxconn до 4096 и tcp_max_syn_backlog до 2048 сократило количество ошибок «Недоступно» на 92% без закупки нового железа. Экспертный вывод: всегда синхронизируйте лимиты ядра ОС с настройками веб-сервера (например, параметр backlog в Nginx), иначе узким местом станет именно ядро.

Тайм-ауты Keep-Alive и утечка дескрипторов

Слишком длинный keepalive_timeout (например, 65-75 секунд) при высоком трафике «забивает» таблицу соединений. Каждый открытый сокет потребляет дескриптор файла. Если лимит ulimit -n установлен на уровне 1024, сервер перестанет принимать новые запросы уже при 100-150 активных пользователях с медленным интернетом. Ошибка «Недоступно» здесь — следствие исчерпания ресурсов ОС на уровне дескрипторов.

Сравнение: установка тайм-аута в 15 секунд вместо 65 сокращает время удержания соединения в 4.3 раза, высвобождая ресурсы для новых сессий. Однако слишком агрессивный тайм-аут (< 5 сек) увеличит нагрузку на TLS-handshake на 20-30%. Экспертный вывод: оптимальный баланс для высоконагруженных систем — 10-15 секунд; всё, что выше, превращает ваш сервер в «хранилище» спящих соединений.

Тонкая настройка HTTP/2 и gRPC лимитов

Переход на HTTP/2 снизил задержки, но ввел новые риски: мультиплексирование позволяет передавать множество запросов в одном TCP-соединении. Если http2_max_concurrent_streams настроен некорректно (стандарт часто 100), а клиент запрашивает 150 ресурсов, возникают внутренние очереди, которые могут привести к тайм-ауту шлюза (504 Gateway Timeout) и статусу «Недоступно» для конечного пользователя.

Практика показывает, что ограничение потоков до 50-80 при одновременном увеличении количества соединений работает стабильнее, чем один «раздутый» поток на 200 запросов. Это предотвращает Head-of-Line Blocking на уровне приложения. Экспертный вывод: не полагайтесь на дефолты HTTP/2; ограничивайте количество потоков, чтобы распределить нагрузку равномерно и избежать каскадных сбоев.

Сетевой стек: TCP Fast Open и TIME_WAIT

Состояния TIME_WAIT — скрытый убийца доступности. При интенсивном обмене короткими запросами порты переходят в режим ожидания (обычно 60 секунд), и новые соединения становятся невозможными из-за исчерпания эфемерных портов (диапазон обычно 32768-60999). Когда количество соединений в TIME_WAIT переваливает за 30 000, сайт переходит в статус «Недоступно».

Решение заключается в активации net.ipv4.tcp_tw_reuse = 1, что позволяет повторно использовать сокеты. В сочетании с TCP Fast Open (TFO) это сокращает время установления соединения на 1 RTT, что критично для мобильных сетей с пингом > 100 мс. Экспертный вывод: для API-сервисов и высоконагруженных сайтов включение tcp_tw_reuse обязательно, иначе вы упретесь в лимит портов задолго до лимита памяти.

Вывод

Чтобы навсегда забыть о статусе «Недоступно» при нагрузках, начните с расширения лимитов дескрипторов (ulimit до 65535) и настройки net.core.somaxconn. Избегайте чрезмерно длинных keepalive-тайм-аутов и обязательно активируйте tcp_tw_reuse. Мой выбор: жесткое ограничение потоков HTTP/2 и синхронизация тайм-аутов между Nginx и Backend-сервисом (Backend timeout должен быть всегда чуть больше, чем Frontend timeout), чтобы исключить «зависание» запросов в очереди.

Читайте также

Эта тема — часть большого разбора: Недоступно.

VK
Pinterest
Telegram
WhatsApp
OK