Когда TCP-соединение считается бездействующим?

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

интервал между последним отправленным пакетом данных (простые ACK не считаются данными) и первым подтверждением активности; после того, как соединение помечено как требующее поддержания активности, этот счетчик больше не используется

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

В моем тестовом примере у меня есть соединение, при котором данные отправляются с сервера клиенту только с довольно высокой скоростью. Чтобы протестировать поддержку активности, мы отключили кабель от сетевой карты клиента. Теперь я вижу, что сетевой стек пытается отправить данные и входит в состояние повторной передачи, но проверка активности не отправляется. Правильно ли, что во время повторной передачи пробы подтверждения активности не отправляются?


person Jens    schedule 20.06.2016    source источник
comment
Если вы «отправляете с довольно высокой скоростью», ваше «требование включить поддержку активности TCP» в первую очередь не имеет смысла.   -  person user207421    schedule 20.06.2016
comment
@EJP У нас есть другие связи, например. не отправляют никаких данных, а другие отправляют только по низким тарифам. Кроме того, это требование, непосредственно возложенное на нас нашим заказчиком. Они используют его глобально.   -  person Jens    schedule 20.06.2016
comment
Я предполагаю, что вы имеете в виду настройку SO_KEEPALIVE для всех ваших подключений (по умолчанию отключено)? Если это так, вы увидите пакет проверки активности только после (по умолчанию в Linux это 2 часа), но тогда трюк с отключением должен сработать (если он не отправляет никаких других данных).   -  person rogerdpack    schedule 30.12.2017
comment
@rogerdpack Да, нам пришлось включить поддержку активности для всех соединений по умолчанию в качестве обязательного требования клиента. Время до отправки первого пакета проверки активности также включает время повторной попытки TCP. ответ cnicutar содержит подробности.   -  person Jens    schedule 31.12.2017


Ответы (1)


У меня есть соединение, при котором данные отправляются с сервера клиенту только с довольно высокой скоростью.

Тогда вы никогда не увидите Keepalive. Keepalives отправляются, когда "молчание на проводе". RFC1122 содержит некоторые пояснения относительно поддержки активности.

Механизм «поддержки активности» периодически проверяет другой конец соединения, когда соединение бездействует, даже если нет данных для отправки.

Вернемся к вашему вопросу:

Некоторые другие источники утверждают, что это время бездействия соединения, но не уточняют, что это означает.

Это то, как долго TCP будет ждать, прежде чем ткнуть пиру «привет! все еще жив?».

$ cat /proc/sys/net/ipv4/tcp_keepalive_time
7200

Другими словами, вы использовали TCP-соединение, и это было здорово. Однако за последние 2 часа не было ничего, чтобы отправить. Разумно ли предположить, что соединение все еще живо? Разумно ли предположить, что все промежуточные блоки в середине все еще имеют информацию о вашем соединении? Мнения расходятся, и сообщения поддержки активности не являются частью RFC793.

Спецификация TCP не включает механизм поддержки активности, который может: (1) привести к разрыву совершенно хороших соединений во время временных сбоев в Интернете; (2) потреблять ненужную полосу пропускания («если никто не использует соединение, какая разница, хорошо ли оно по-прежнему?»)


Чтобы протестировать поддержку активности, мы отключили кабель от сетевой карты клиента.

Это не проверка активности. Это проверяет вашу стратегию повторной передачи TCP, т. е. сколько раз и как часто TCP будет пытаться передать ваше сообщение. В системе Linux это (вероятно) заканчивается тестированием net.ipv4.tcp_retries2:

Сколько раз можно повторить попытку, прежде чем убить живое TCP-соединение. RFC 1122 говорит, что ограничение должно быть больше 100 секунд. Это слишком маленькое число. Значение по умолчанию 15 соответствует 13-30 мин в зависимости от RTO.

Но RFC5482 — параметр тайм-аута пользователя TCP предоставляет больше способов повлиять на него.

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

Вернемся к вопросу:

Верно ли, что во время повторной передачи зонды проверки активности не отправляются?

В этом есть смысл: TCP уже пытается получить ответ от другого узла, пустое подтверждение активности было бы излишним.


Специфичные для Linux (2.4+) параметры, влияющие на поддержку активности

  • TCP_KEEPCNT Максимальное количество запросов проверки активности, которые TCP должен отправить перед разрывом соединения.

  • TCP_KEEPIDLE Время (в секундах), в течение которого соединение должно оставаться бездействующим, прежде чем TCP начнет отправлять проверки активности, если для этого сокета была установлена ​​опция сокета SO_KEEPALIVE

  • TCP_KEEPINTVL Время (в секундах) между отдельными проверками активности

Для Linux (2.6.37+) параметр, влияющий на тайм-аут пользователя TCP

TCP_USER_TIMEOUT Максимальное количество времени в миллисекундах, в течение которого передаваемые данные могут оставаться неподтвержденными, прежде чем TCP принудительно закроет соединение.

Так, например, ваше приложение может использовать эту опцию, чтобы определить, как долго сохраняется соединение при отсутствии подключения (аналогично вашему примеру с отключением сетевой карты). Например. если у вас есть основания полагать, что клиент вернется (возможно, он закрыл крышку ноутбука? нестабильный беспроводной доступ?), вы можете указать тайм-аут в 12 часов, и когда он вернется, соединение все еще будет работать.

person cnicutar    schedule 20.06.2016
comment
К вашему сведению, Linux 2.4+ имеет параметры TCP_KEEPIDLE, TCP_KEEPINTVL и TCP_KEEPCNT для setsockopt(), чтобы установить время простоя до начала проверки, временной интервал между проверками и максимальное количество запросов для отправки соответственно. - person Remy Lebeau; 20.06.2016
comment
@RemyLebeau Аккуратный. Не стесняйтесь редактировать ответ, чтобы указать на это! - person cnicutar; 20.06.2016
comment
@cnicutar У вас есть источник, на который я могу сослаться, в котором описывается, что во время повторной передачи никакие проверки активности не отправляются? Кажется, что это отличается от системы к системе, например. в винде вроде по другому. - person Jens; 21.06.2016
comment
@Jens У меня нет источника. Не является незаконным продолжать отправлять проверки активности, но в этом мало смысла: если TCP уже отправляет что-то, уже есть причина для другой стороны для ACK (что доказывает, что соединение активно). - person cnicutar; 21.06.2016
comment
@cnicutar отличный ответ. Его можно немного улучшить, включив также информацию о TCP_USER_TIMEOUT в Linux. Похоже, что OP и другие захотят узнать, как установить тайм-аут повторной передачи для каждого соединения при поиске ответов о том, почему Keep Alive работает только с соединениями, которые простаивают или ожидают данных, которые не приходят. - person Kurt M; 31.05.2017
comment
@KurtM Я добавил еще несколько деталей. Не стесняйтесь редактировать ответ, чтобы добавить все, что вы считаете полезным. - person cnicutar; 11.06.2017