Диагностика задержек TCP: анализ Window Size, Zero Window и SACK
- Резкое падение скорости передачи данных внутри высокоскоростного канала (10 Gbps) до нескольких мегабит в секунду.
- Появление в дампе Wireshark предупреждений
[TCP ZeroWindow],[TCP Window Full]и[TCP Retransmission]. - Зависание сессий передачи файлов (SMB, iSCSI, HTTP REST) с регулярными паузами на несколько секунд.
- Высокий процент повторных подтверждений
[TCP Dup ACK], свидетельствующий о потере пакетов в транзитной сети.
1. Анатомия TCP Windowing и причины зависаний
Размер окна приема (**Receive Window / RWIN**) сообщает отправителю, сколько байт данных получатель готов принять в свой системный буфер до получения подтверждения (ACK). Событие TCP Zero Window означает, что буфер приложения на стороне получателя полностью забит, и отправитель обязан полностью остановить передачу (Window Probe pause).
2. Анализ TCP потока в Wireshark
# Фильтры для выявления проблем производительности TCP в Wireshark
tcp.analysis.zero_window
tcp.analysis.window_full
tcp.analysis.retransmission
tcp.analysis.duplicate_ack
# Меню Wireshark для графического анализа:
# Statistics -> TCP Stream Graphs -> Time-Sequence-Graph (Stevens)
# Statistics -> TCP Stream Graphs -> Window Scaling3. Оптимизация буферов TCP сокетов в Linux (Sysctl)
Если сервер генерирует Zero Window из-за нехватки системных буферов, скорректируйте параметры в /etc/sysctl.d/99-tcp-performance.conf:
# Включение масштабирования окна (Window Scaling, RFC 1323)
net.ipv4.tcp_window_scaling = 1
# Включение выборочного подтверждения (Selective ACK, SACK)
net.ipv4.tcp_sack = 1
# Увеличение максимального размера буферов приема/передачи (min, default, max байт)
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
# Включение современного алгоритма контроля перегрузки BBR
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbrsysctl --system4. Проверка состояния сокетов через утилиту `ss`
# Детальный просмотр параметров окна и RTT конкретного соединения
ss -t -i -e 'sport = :443 or dport = :443' Частые вопросы (FAQ)
Что означает предупреждение 'TCP Window Full' в Wireshark?
Это означает, что отправитель передал весь доступный объем данных, разрешенный текущим окном получателя (RWIN), и теперь вынужден простаивать в ожидании подтверждения ACK от принимающей стороны.
Зачем нужен механизм SACK (Selective Acknowledgement)?
Без SACK при потере одного пакета из цепочки отправитель вынужден повторно передавать ВСЕ пакеты, начиная с потерянного (Go-Back-N). SACK позволяет получателю точно указать, какие именно не непрерывные блоки данных он успешно принял, сокращая повторный трафик.
Почему при наличии свободной полосы 1 Gbps скорость упирается в 10 Mbps при RTT = 100ms?
Если на хостах отключен Window Scaling, максимальный размер TCP Window ограничен 65 535 байтами (64 КБ). По формуле пропускной способности: Throughput = Window Size / RTT = 65535 * 8 / 0.1 сек ≈ 5.24 Mbps.
Что такое TCP Keepalive и Zero Window Probe?
Когда окно схлопывается в ноль, отправитель периодически шлет 1-байтные пакеты Zero Window Probe. Получатель отвечает TCP Keepalive ACK, сообщая актуальный размер освободившегося буфера.