Почему TCP-ретрансмиссии останавливают связь с промышленной камерой, и как это диагностировать

· · TCP, Сети, Расследование сбоев, Разработка Windows, Промышленная камера

В связи с промышленными камерами и управлением оборудованием самое неприятное явление — это когда в среднем всё быстро, но изредка возникает остановка на несколько секунд. Воспроизводимость низкая, обычно ничего не происходит, поэтому подозрительными по очереди начинают казаться UI, потоки, GC, SDK камеры, сетевая карта, коммутатор — буквально всё.

В этой статье разбирается случай, когда TCP-связь между хостом и приложением, управляющим промышленной камерой, изредка останавливалась на несколько секунд. При исследовании выяснилось, что дело не в остановке приложения, а в ожидании TCP-ретрансмиссии из-за потери пакета. Более того, включение функции меток времени семейства RFC1323 (в актуальной систематизации — RFC 7323) позволило свести время ожидания к минимуму именно в этой системе.

Названия устройств, конфигурация и цифры обобщены, но сам подход напрямую применим на практике.

Содержание

  1. Сначала — вывод (в двух словах)
  2. Как проявлялся симптом
    • 2.1. Приложение живо, но отклик останавливается на секунды
    • 2.2. Низкая частота затрудняет анализ по одним лишь логам
  3. Что происходило на самом деле (с диаграммами)
    • 3.1. От потери пакета к ожиданию повторной передачи
    • 3.2. Остановки на секунды совпадали по форме с RTO
  4. На что смотрели при расследовании
    • 4.1. Сначала исключаем причины остановки внутри приложения
    • 4.2. Подтверждаем повторные передачи по захвату пакетов
    • 4.3. Смотрим, какие опции TCP были согласованы
  5. Почему помогают метки времени RFC1323
    • 5.1. Метки времени служат для RTTM и PAWS
    • 5.2. Можно снять неоднозначность измерения RTT при повторной передаче
    • 5.3. Почему в этом случае удалось сократить время ожидания
  6. Что было реально сделано
    • 6.1. Включаем метки времени
    • 6.2. Проверяем TSopt в SYN / SYN-ACK
    • 6.3. Куда смотреть, если всё равно не помогает
  7. На что смотреть в Wireshark
  8. Как выбирать (кратко)
  9. Итог
  10. Справочные материалы

1. Сначала — вывод (в двух словах)

  • TCP-связь, изредка останавливающаяся на несколько секунд, иногда объясняется не остановкой приложения, а ожиданием повторной передачи после потери пакета
  • Если в захвате пакетов видна Retransmission с большим временным разрывом, а длительность остановки совпадает с тем, как ведёт себя ожидание RTO, — это весьма подозрительно
  • Опция TCP timestamps — механизм для измерения RTT и PAWS, и она же снимает неоднозначность измерения RTT при повторной передаче
  • В этом случае включение функции меток времени семейства RFC1323 сократило время, в течение которого оценка RTO оставалась устаревшей и излишне консервативной, сведя остановки в секундах к минимуму
  • Однако это не волшебство, устраняющее саму потерю. Отдельно всё равно нужно пересматривать физический уровень, сетевую карту, коммутатор, промежуточное оборудование, драйверы и проектирование буферов

Иначе говоря, если истинная причина «изредка останавливается на несколько секунд» — это время ожидания внутри TCP, то одни лишь усилия по доработке повторов на стороне приложения бьют мимо цели. Быстрее сначала посмотреть на wire и убедиться, идёт ли речь именно об ожидании повторной передачи.

2. Как проявлялся симптом

2.1. Приложение живо, но отклик останавливается на секунды

Первое, что сбивает с толку, — приложение в целом не выглядит зависшим.

  • UI не полностью мёртв;
  • процесс не упал;
  • CPU не прибит к потолку;
  • но отклик на команды управления камерой изредка пропадает на несколько секунд.

Такие симптомы трудно отличить от deadlock или бесконечного цикла внутри приложения. К тому же в управлении оборудованием одна остановка на несколько секунд сразу воспринимается как остановка линии. Даже если усреднённые показатели выглядят чисто, восприятие на месте оказывается заметно хуже.

2.2. Низкая частота затрудняет анализ по одним лишь логам

Неприятность такого рода дефектов — в низкой частоте появления. Раз в час, раз в полдня, только при совпадении условий — примерно так это выглядит.

Если пытаться отследить только по логам, обычно получается так:

  • в логе приложения всё останавливается на «отправили», «ответ не пришёл»;
  • в логе принимающей стороны выглядит как «ничего не приходило»;
  • в то же самое время случайно происходит другое событие, и подозреваемые расходятся в стороны.

В такой ситуации попытка восстановить причинно-следственную связь только по логам приложения довольно надёжно заводит в болото. Быстрее спуститься на уровень ниже, к уровню связи.

3. Что происходило на самом деле (с диаграммами)

3.1. От потери пакета к ожиданию повторной передачи

Сюжет на этот раз простой. Где-то по пути терялся пакет, отправитель ждал ACK, тот не приходил, поэтому отправитель ждал истечения RTO и лишь затем повторял отправку.

Сторона камерыСетьХост-приложениеСторона камерыСетьХост-приложениездесь потеряACK не приходит, поэтому ждёмвосстановление этого запроса требует ожидания RTOздесь связь возобновляетсякоманда управления (Seq=N)повторная отправка команды управленияповторный пакет доходитACKACK

Со стороны приложения это выглядит как «остановка на несколько секунд», но с точки зрения TCP это просто «ACK ещё не пришёл, поэтому мы ждём истечения таймера повторной передачи». Неброско, но такая форма остановки — обычное дело.

Управляющая связь в этом случае состояла в основном из небольших обменов запрос/ответ, и за один обмен в полёте не оказывалось большого объёма неподтверждённых данных. Поэтому в такой конфигурации ожидание RTO чаще проявлялось раньше, чем успевало набраться достаточно duplicate ACK для fast retransmit.

3.2. Остановки на секунды совпадали по форме с RTO

Ожидание повторной передачи TCP, хотя и зависит от реализации, ведёт себя консервативно. Согласно RFC 6298, начальный RTO принимается за 1 секунду; если расчётное значение меньше, оно округляется до 1 секунды, а при каждом тайм-ауте — удваивается.

ДаНетПотеря пакетаACK не приходитОжидание RTOПовторная отправкаACK вернулся?Связь возобновляетсяRTO удваивается

Поэтому даже там, где хотелось бы уложиться в несколько сотен миллисекунд, при неблагоприятных условиях ожидание может выглядеть как 1, 2, 4 секунды. «Изредка возникающая остановка на несколько секунд» в этом случае довольно точно совпала именно с такой формой.

4. На что смотрели при расследовании

4.1. Сначала исключаем причины остановки внутри приложения

Не бросаясь сразу обвинять TCP, сначала исключили типичные причины на стороне приложения.

Что проверяли Зачем смотрели Вывод в этом случае
UI-поток / рабочие потоки Проверка зависаний и взаимных ожиданий Не была основной причиной
Загрузка CPU Проверка задержек обработки из-за высокой нагрузки Не была прибита к потолку даже во время остановок
GC / нехватка памяти Проверка пауз Форма длительности остановок не совпадала
Вызовы SDK камеры Проверка ожиданий внутри SDK Не совпадало с задержками на wire
Захват пакетов Проверка повторных передач на уровне связи Здесь и обозначилась причина

Важно здесь — не назначать виновного только по времени в логе приложения. В приложениях управления оборудованием ожидание на верхнем уровне иногда просто отражает ожидание на нижнем.

4.2. Подтверждаем повторные передачи по захвату пакетов

При захвате пакетов в интервале остановки было видно TCP Retransmission, а непосредственно перед этим — что ACK не возвращался.

Стоит смотреть примерно на следующее.

  • появляется ли повторная передача с тем же Seq;
  • совпадает ли временной разрыв до повторной передачи с длительностью остановки;
  • похоже ли это на ожидание истечения RTO, а не на Dup ACK или Fast Retransmission;
  • проявляется ли проблемное соединение каждый раз в одном и том же tcp.stream.

Если всё это совпадает, версия «TCP ждёт повторной передачи», а не «приложение зависло», становится заметно весомее.

4.3. Смотрим, какие опции TCP были согласованы

Следующее, на что посмотрели, — SYN / SYN-ACK при установлении соединения. Метки времени согласовываются в ходе тройного рукопожатия TCP, поэтому если TSopt там не появляется, на этом соединении она не используется.

Сторона камерыХостСторона камерыХосттолько после согласования здесь TSopt можно использовать в последующих сегментахSYN + TSopt ?SYN/ACK + TSopt ?ACK

Если трогать настройки ОС, не посмотрев на это, легко получить ещё одну неброскую неприятность: «вроде бы включил, а не работает». Факты на wire весомее значений в настройках.

5. Почему помогают метки времени RFC1323

На практике название «метки времени RFC1323» всё ещё в ходу, хотя действующей систематизацией является RFC 7323. В этой статье мы, следуя обычаю, пишем RFC1323, подразумевая под этим TCP timestamps option.

5.1. Метки времени служат для RTTM и PAWS

Опция timestamps в TCP используется в основном для двух целей.

  • RTTM (Round-Trip Time Measurement — измерение времени кругового пути);
  • PAWS (Protect Against Wrapped Sequences — защита от переполнения номеров последовательности).

В этом случае сработала сторона RTTM. Отправив сегмент со значением TSval, отправитель получает его обратно в поле TSecr ACK-а от собеседника, благодаря чему может измерять RTT точнее и мельче.

5.2. Можно снять неоднозначность измерения RTT при повторной передаче

При повторной передаче без меток времени возникает неоднозначность: «этот ACK относится к первоначальной отправке или к повторной?» Именно об этом беспокоится так называемый алгоритм Карна.

RFC 6298 говорит, что для повторно отправленных сегментов брать RTT-выборку нельзя — потому что непонятно, к какой именно отправке относится ACK. Но при наличии опции timestamps эту неоднозначность можно снять: посмотрев на TSecr, приходящий в ACK, можно определить, какой именно сегмент, с каким TSval, дошёл.

ПолучательОтправительПолучательОтправительэтот сегмент теряетсяACK не приходит, поэтому ждёмможно определить, на какую отправку это ответSeq=N, TSval=1000повторно отправляем Seq=N, TSval=2000ACK, TSecr=2000

Именно в этом суть улучшения в этом случае.

5.3. Почему в этом случае удалось сократить время ожидания

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

Иначе говоря, сделанное в этом случае — не волшебство, ускоряющее TCP, а сокращение времени, в течение которого TCP излишне долго выжидает.

Разумеется, RFC 7323 тоже не утверждает, что «больше RTT-выборок аккуратно решает всё». Степень пользы для оптимизации RTO в некоторых отношениях ограничена. Тем не менее тот факт, что удаётся снять неоднозначность при повторной передаче, в системе вроде этой может сработать вполне заметно.

Есть и предостережения.

  • часть этого зависит от реализации TCP-стека;
  • сами по себе метки времени не устраняют потерю пакетов;
  • если виноват физический уровень или промежуточное оборудование, первопричина лежит в другом месте;
  • SACK, драйверы сетевой карты, настройки offload и проблемы на стороне коммутатора стоит рассматривать отдельно.

Тем не менее в системе, подобной этой, где «потери не равны нулю», но «по-настоящему болезненны именно секундные ожидания», это может дать заметный эффект.

6. Что было реально сделано

6.1. Включаем метки времени

В качестве меры мы добились того, чтобы опция timestamps могла согласовываться на обоих концах соединения. В системах на базе Windows это иногда трактуется как опция RFC 1323 и зависит от настроек ОС и сети.

Тем не менее на практике важнее не «включено в окне настроек», а «TSopt действительно присутствует в реальных пакетах SYN / SYN-ACK». Здесь это действительно так.

6.2. Проверяем TSopt в SYN / SYN-ACK

После включения проверили три момента.

  • есть ли TSopt в SYN проблемного соединения;
  • возвращает ли TSopt и сторона SYN/ACK;
  • продолжают ли последующие сегменты данных и ACK нести TSopt.

Только убедившись во всём этом, можно сказать, что «на этом соединении метки времени действительно используются».

6.3. Куда смотреть, если всё равно не помогает

Даже после включения меток времени улучшение бывает вялым в таких случаях.

  • сам процент потерь высок;
  • промежуточное оборудование портит, отбрасывает или искажает опции TCP;
  • есть отдельная проблема вокруг сетевой карты / драйвера / offload;
  • приложение подвешивает всё на один синхронный вызов, из-за чего одно ожидание выглядит как полная остановка;
  • реальная причина вовсе не в TCP, а в остановке обработки на стороне камеры или заторе во внутренней очереди устройства.

Поэтому логичнее двигаться в таком порядке.

  1. сначала подтвердить ожидание повторной передачи на wire;
  2. проверить, согласуется ли TSopt;
  3. включить метки времени и оценить разницу в улучшении;
  4. если проблема остаётся, отдельно разбираться с источником потерь и проектированием приложения.

7. На что смотреть в Wireshark

Приведём удобные для диагностики фильтры отображения.

tcp.stream eq <нужный поток>
tcp.analysis.retransmission
tcp.analysis.fast_retransmission
tcp.analysis.lost_segment
tcp.options.timestamp.tsval
tcp.options.timestamp.tsecr

Есть несколько приёмов для чтения результатов.

  • сузить выборку до нужного соединения через tcp.stream;
  • вывести Time delta from previous displayed packet, чтобы напрямую увидеть длительность остановки в секундах;
  • проверить, появляется ли Retransmission в нужный момент;
  • проверить, согласуется ли TSopt в SYN / SYN-ACK при установлении соединения;
  • посмотреть, возвращается ли TSecr в ACK.

При сопоставлении логов и пакетов стоит учитывать и расхождение эталонов времени между приложением и захватом. Если здесь есть смещение, легко назначить виновным не то событие.

8. Как выбирать (кратко)

Симптом Что подозревать в первую очередь Что сделать сначала
Изредка останавливается на несколько секунд Ожидание RTO в TCP Подтвердить повторные передачи и временной разрыв по пакетам
Останавливается почти в одно и то же время каждый раз Ожидание внутри приложения, обработка на стороне устройства, фиксированные тайм-ауты Посмотреть потоки, вызовы SDK, логи устройства
Ухудшается только при высокой нагрузке CPU, GC, затор в очереди Посмотреть CPU, прерывания, память, длину очереди
Плохо сразу на широком диапазоне соединений Физический уровень, коммутатор, промежуточное оборудование Посмотреть сетевую карту, кабели, статистику портов, логи промежуточного оборудования
Настройки изменили, а ничего не поменялось Опция TCP не согласуется Перепроверить SYN / SYN-ACK

Последняя строка встречается действительно часто. Удовлетворение от того, что настройку поменяли, и факт того, что она реально используется на wire, — это разные вещи.

9. Итог

Основные моменты на этот раз:

  • «изредка останавливается на несколько секунд» может быть не остановкой приложения, а ожиданием TCP-ретрансмиссии;
  • если длительность остановки совпадает с тем, как ведёт себя ожидание RTO, и видна Retransmission, версия весьма правдоподобна;
  • опция TCP timestamps — механизм для RTTM и PAWS, и она же снимает неоднозначность измерения RTT при повторной передаче;
  • в этом случае включение меток времени семейства RFC1323 сдержало время, в течение которого RTO оставался чрезмерно консервативным.

Подходов, которых стоит избегать:

  • назначать виновника остановки связи только по логам приложения;
  • смотреть только на настройки ОС, не глядя на реальные пакеты;
  • думать, что включение меток времени устранит и причину потерь.

Подходов, которые работают на практике:

  • сначала посмотреть на wire;
  • проверить форму повторных передач и времени ожидания;
  • проверить согласование TSopt;
  • даже после улучшения отдельно разбираться с источником потерь и проектированием приложения.

Иначе говоря, при дефектах такого рода «понять, где именно идёт ожидание» важнее, чем «ускорить». Не упуская именно этот момент, можно заметно сократить время расследования.

10. Справочные материалы

Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.

Реагирование на инциденты не заканчивается восстановлением — шаблон постмортема (предотвращения повторения) для небольших команд разработки

Считать инцидент закрытым сразу после исправления и извинений — гарантированный способ повторить его снова. Адаптируем blameless-постморт...

Спящий режим, гибернация, Modern Standby и долго работающие приложения — как проектированием предотвратить «остановилось ночью»

Разбираем, почему долго работающее Windows-приложение оказывается «остановленным к утру», начиная с различий между спящим режимом S3, гиб...

Если вам досталась система без исходного кода и без документации — практический план, как сопровождать её, не останавливая работу

Разбираем практический план начала эксплуатации и сопровождения бизнес-системы, у которой нет ни исходного кода, ни спецификаций. Охватыв...

Эти страницы показывают тему статьи в более широком контексте услуг и решений.

В этих примерах используется сходный подход к анализу, расстановке приоритетов или переработке.

Статья напрямую связана со следующими услугами.

Частые вопросы

Вопросы, которые часто возникают при консультациях по теме статьи.

Что такое TCP Retransmission (повторная передача TCP)?
Механизм, при котором TCP повторно отправляет те же данные, если на отправленный пакет не вернулся ACK (подтверждение). Если где-то по пути пакет теряется, отправитель ждёт ACK, и, если он не приходит, ждёт истечения таймера повторной передачи (RTO) и лишь затем повторяет отправку. Со стороны приложения это выглядит как «остановка на несколько секунд», но с точки зрения TCP это просто «ACK ещё не пришёл, поэтому ждём истечения таймера повторной передачи» — такая форма остановки вполне обычна. В захвате пакетов это видно как TCP Retransmission.
По какой причине возникает TCP Retransmission?
Непосредственный триггер — потеря пакета: из-за неё не возвращается ACK, и происходит повторная отправка. Источник потери нужно смотреть отдельно — это может быть физический уровень (кабель, порт), сетевая карта или её драйвер и настройки offload, проблемы на коммутаторе или промежуточном оборудовании. Включение TCP timestamps может сократить время ожидания после повторной передачи, но это не волшебство, устраняющее саму потерю, — источник потерь нужно исследовать отдельно. Бывают и случаи, когда промежуточное оборудование портит или отбрасывает опции TCP, а также случаи, где главная причина — вовсе не TCP, а остановка обработки на стороне устройства.
Почему из-за TCP-ретрансмиссии связь останавливается на целые секунды?
Потому что таймер повторной передачи TCP (RTO) ведёт себя консервативно. Согласно RFC 6298, начальный RTO принимается за 1 секунду, и даже если расчётное значение меньше, оно округляется до 1 секунды, а при каждом тайм-ауте удваивается. Поэтому при неблагоприятных условиях ожидание может выглядеть как 1, 2, 4 секунды. В управляющей связи с преобладанием небольших запросов и ответов ожидание RTO часто проявляется раньше, чем успевает набраться достаточно duplicate ACK для fast retransmit, — и это выглядит как редкая остановка на несколько секунд. Включение опции TCP timestamps в ряде случаев позволяет снять неоднозначность измерения RTT при повторной передаче и сократить время, в течение которого оценка RTO остаётся чрезмерно консервативной.
Как проверить TCP Retransmission в Wireshark?
В качестве фильтров отображения можно использовать tcp.analysis.retransmission, tcp.analysis.fast_retransmission, tcp.analysis.lost_segment и подобные. Сузьте выборку до нужного соединения через tcp.stream, выведите Time delta from previous displayed packet, чтобы напрямую увидеть длительность остановки в секундах, и проверьте, появляется ли Retransmission в нужный момент и совпадает ли временной разрыв до повторной передачи с длительностью остановки. Используются ли TCP timestamps, проверяется по тому, согласовывается ли TSopt в SYN / SYN-ACK при установлении соединения. Важнее не то, что опция включена в настройках, а факт наличия TSopt в реальных пакетах.

Об авторе

Страница с профилем автора статьи.

Го Комура

Представитель KomuraSoft LLC

Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.

Публичные ссылки

Вернуться в блог