Назад | Перейти на главную страницу

Подтверждения TCP приостанавливаются, затем возобновляются, а затем снова приостанавливаются. Зачем?

Мне нужна помощь в поиске причины снижения скорости передачи данных в моем приложении.

У меня 12 встроенных систем и Linux-сервер. Встроенные системы отправляют данные на сервер по TCP по каналу Ethernet через коммутатор. Ниже приведен TCP StreamGraph, созданный на основе захвата Wireshark трафика с одной платы.

Как видите, скорость передачи данных составляет от 5,8 МБит / с до 0,25 секунды. Это настолько быстро, насколько я могу ожидать от встроенной системы. После этого в перевод вставляются задержки. Ниже показан крупный план графика:

Лестничная кривая внизу с надписью ACK показывает, сколько данных было подтверждено сервером в любой момент времени. Соответствующая кривая RWIN показывает, сколько места будет в буферах на datapc. Меньшие вертикальные сегменты, помеченные SENT DATA, представляют собой фактические отправленные пакеты.

В точке A сервер подтверждает данные так же быстро, как они отправлены, но затем в течение 23 мс сервер не отправляет подтверждения. Встроенной системе разрешено отправлять в RWIN, не дожидаясь подтверждения ACK, но она не делает этого, потому что ей необходимо хранить отправленные данные до тех пор, пока они не будут подтверждены (в случае их повторной передачи), а пространство буфера отправки будет ограниченное.

Затем в точке B все полученные данные сразу подтверждаются, и нормальное подтверждение и отправка возобновляются на 2,5 мс, прежде чем произойдет еще одна пауза.

Захват Wireshark был сделан с другого ПК, который был подключен к порту на коммутаторе, который был настроен для зеркалирования всех данных, отправленных и полученных через порт, к которому была подключена встроенная система.

Сервер Linux запускает приложение Java, которое обрабатывает данные и сохраняет их на диске. Он не показывает никаких признаков максимальной загрузки ЦП. Операционная система - Ubuntu Server 12.04 с сетевыми настройками по умолчанию.

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

Мои вопросы:

  1. В чем может быть причина того, что сервер Linux приостанавливает ACK, хотя он, очевидно, может получать все нормально?
  2. Как я могу отладить это?

Попробуйте отключить кадры Ethernet PAUSE с помощью ethtool -A devname autoneg off rx off tx off

Если это не помогает, это может быть проблема масштабирования TCP-окон и / или проблема со штормом IRQ на хосте отправителя или получателя. Вы можете исследовать обе проблемы, пробуя разные настройки с помощью ethtool и записи sysctl, регулирующие TCP-трафик.

Без другой информации довольно сложно сказать, что здесь происходит ...

Другой очевидный вопрос: почему клиенты перестают отправлять? Обычно клиент не останавливается и не ждет ACK перед отправкой следующего TCP-пакета. Возможно, они отправляют однобайтовые сообщения, которые задерживаются алгоритмом Нэгла?

https://en.wikipedia.org/wiki/Nagle%27s_algorithm

Если это так, и ваш сервер Linux использует отложенное подтверждение TCP, тогда вы можете ожидать задержки ACK до 500 мс.

https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment

Если это так, то ее легко исправить, используя более крупные сообщения или отключив алгоритм Нэгла во встроенных системах (TCP_NODELAY).