Где находятся возможные места задержки очереди / буферизации в многоадресной рассылке Linux? - PullRequest
2 голосов
/ 18 февраля 2010

Мы интенсивно используем многоадресную передачу сообщений на многих серверах Linux в локальной сети.Мы видим много задержек.Мы в основном отправляем огромное количество маленьких посылок.Мы больше озабочены задержкой, чем пропускной способностью.Все машины являются современными, многоядерными (по крайней мере, четыре, обычно восемь, 16, если считать гиперпоточность), всегда с нагрузкой 2,0 или менее, обычно с нагрузкой менее 1,0.Сетевое оборудование также имеет емкость менее 50%.

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

Структура обмена сообщениями в основном такова: в «потоке отправки» извлекайте сообщения из очереди, добавляйте метку времени (используя gettimeofday()), затем вызывайте send().Принимающая программа получает сообщение, ставит метки времени получения и помещает его в очередь.В отдельном потоке очередь обрабатывается, анализируя разницу между временными метками отправки и получения.(Обратите внимание, что наши внутренние очереди не являются частью проблемы, поскольку временные метки добавляются за пределы нашей внутренней очереди.)

На самом деле мы не знаем, с чего начать искать ответ на эту проблему.Мы не знакомы с внутренностями Linux.Мы подозреваем, что ядро ​​ставит в очередь или буферизует пакеты либо на стороне отправки, либо на стороне приема (или обоих).Но мы не знаем, как это отследить и отследить.

Для чего бы то ни было, мы используем CentOS 4.x (ядро RHEL 2.6.9).

Ответы [ 3 ]

3 голосов
/ 19 февраля 2010

Это отличный вопрос.В CentOS, как и в большинстве разновидностей * nix, для каждого многоадресного сокета есть буфер приема / отправки UDP.Размер этого буфера контролируется sysctl.conf. Вы можете просмотреть размер ваших буферов, вызвав / sbin / sysctl -a

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

[~] $ / sbin / sysctl -a |mem net.core.rmem_default = 16777216 net.core.wmem_default = 16777216 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216

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

последнее, что вы можете сделать (в зависимости от версии вашего ядра), это просмотреть статистику UDP PID для вашего процесса или, по крайней мере, в целом.

cat / proc / net / snmp |grep -i Udp Udp: InDatagrams NoPorts InErrors OutDatagrams Udp: 81658157063 145 616548928 3896986

cat / proc / PID / net / snmp |grep -i Udp Udp: InDatagrams NoPorts InErrors OutDatagrams Udp: 81658157063 145 616548928 3896986

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

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

1 голос
/ 19 марта 2010

Если вы решите, что вам нужно захватывать пакеты в производственной среде, возможно, стоит посмотреть на порты монитора на коммутаторах и захватывать пакеты на непроизводственных компьютерах. Это также позволит вам захватывать пакеты в нескольких точках на пути передачи и сравнивать то, что вы видите.

1 голос
/ 19 марта 2010

Пакеты могут стоять в очереди в ядре отправляющей и принимающей стороны, сетевой карте и сетевой инфраструктуре. Вы найдете множество предметов, которые вы можете проверить и настроить.

Для NIC вы обычно можете найти параметры объединения прерываний - сколько времени NIC будет ждать, прежде чем уведомить ядро ​​или отправить по проводу, ожидая пакетных пакетов.

Для Linux у вас есть «буферы» отправки и получения, чем они больше, тем больше вероятность того, что вы получите более высокую задержку при обработке пакетов в пакетных операциях.

Для архитектуры и версии Linux вы должны знать, насколько дорогими являются переключатели контекста и включены ли блокировки или упреждающее планирование. Попробуйте свести к минимуму количество запущенных приложений, используя привязку процессов для привязки процессов к конкретным ядрам.

Не забывайте время: используемая вами версия ядра Linux имеет довольно ужасную точность на gettimeofday() такте (2-4 мс) и является довольно дорогим вызовом. Рассмотрите возможность использования альтернатив, таких как чтение из основного TSC или внешнего устройства HPET.

Диаграмма от Intel: альтернативный текст http://www.theinquirer.net/IMG/142/96142/latency-580x358.png?1272514422

...