tcpdump увеличивает производительность udp

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

Node.js test suite (client) --> StatsD (server) --> Graphite (server)

Короче говоря, набор тестов node.js отправляет определенное количество метрик каждые x секунд в экземпляр StatsD, который находится на другом сервере. Затем StatsD сбрасывает метрики каждую секунду в экземпляр Graphite, расположенный на том же сервере. Затем я смотрю, сколько метрик фактически было отправлено набором тестов и сколько было получено Graphite для определения потери пакетов между набором тестов и Graphite.

Однако я заметил, что иногда я получаю очень большие скорости отбрасывания пакетов (обратите внимание, что он отправляется по протоколу UDP), в диапазоне от 20-50%. И вот тогда я начал изучать, где эти пакеты отбрасывались, понимая, что это может быть связано с некоторой проблемой производительности StatsD. Поэтому я начал регистрировать показатели в каждой части системы, чтобы отслеживать, где произошло это падение. И здесь все становится странным.

Я использую tcpdump для создания файла захвата, который я проверяю после завершения теста. Но всякий раз, когда я запускаю тесты с запущенным tcpdump, потеря пакетов практически отсутствует! Похоже, что tcpdump каким-то образом повышает производительность моих тестов, и я не могу понять, почему и как это происходит. Я запускаю следующую команду для регистрации сообщений tcpdump на сервере и клиенте:

tcpdump -i any -n port 8125 -w test.cap

В одном конкретном тестовом примере я посылаю 40000 метрик / с. Тест при запуске tcpdump имеет потерю пакетов около 4%, в то время как тест без потери пакетов составляет около 20%

Обе системы работают как виртуальные машины Xen со следующей настройкой:

  • Intel Xeon E5-2630 v2 с частотой 2,60 ГГц
  • 2 ГБ ОЗУ
  • Ubuntu 14.04 x86_64

Вещи, которые я уже проверил на возможные причины:

  • Увеличение размера буфера приема / отправки UDP.
  • Нагрузка процессора влияет на тест. (максимальная загрузка 40-50%, как на стороне клиента, так и на стороне сервера)
  • Запуск tcpdump на определенных интерфейсах вместо 'any'.
  • Запуск tcpdump с '-p' для отключения случайного режима.
  • Запуск tcpdump только на сервере. Это привело к потере пакетов на 20% и, похоже, не повлияло на тесты.
  • Запуск tcpdump только на клиенте. Это привело к увеличению производительности.
  • Увеличение netdev_max_backlog и netdev_budget до 2^32-1. Это не имеет значения.
  • Перепробовал все возможные настройки беспорядочного режима на каждом нике (сервер включен и клиент выключен, сервер выключен и клиент включен, оба включены, оба выключены). Это не имеет значения.

4 ответа

Когда tcpdump запущен, он будет довольно быстро читать при поступлении кадров. Моя гипотеза состоит в том, что настройки буфера кольцевого пакета NIC могут быть немного маленького размера; когда tcpdump работает, он очищается более своевременно.

Если вы являетесь подписчиком Red Hat, то эта статья поддержки очень полезна. Обзор приема пакетов. Там есть некоторые вещи, которые, я думаю, вы еще не рассматривали.

Подумайте, как ваша система работает с IRQ; рассмотреть возможность увеличения "dev_weight" сетевого интерфейса (что означает, что больше пакетов будет прочитано из NIC в пространство пользователя); посмотрите, как часто приложение читает сокет (может ли оно использовать выделенный поток, есть ли известные проблемы / обходные пути в отношении масштабируемости).

Увеличить буфер кадров NIC (используя ethtool команда - посмотрите на --set-ring и т.д. аргументы).

Посмотрите на "масштабирование на стороне приема" и используйте хотя бы столько потоков приема для чтения в трафике.

Интересно, делает ли tcpdump что-то классное, например, использует поддержку ядра для кольцевых буферов пакетов? Это поможет объяснить поведение, которое вы видите.

Какого губернатора вы используете? Я видел подобное поведение с "по требованию" или "консервативным" губернатором.

Попробуйте использовать регулятор производительности и отключить все энергосберегающие функции в BIOS сервера.

Это что-то меняет?

Я подозреваю, что принимающая сторона просто не способна обрабатывать скорость передачи пакетов, и вот почему:

  1. использование tcpdump на клиенте уменьшает количество отброшенных пакетов: tcpdump замедляет работу клиента, и поэтому сервер видит гораздо более низкую скорость упаковщика, с которой он все еще может частично справиться. Вы должны быть в состоянии подтвердить эту гипотезу, проверив счетчики пакетов RX/TX на клиенте и сервере

  2. Вы упомянули, что вы увеличили размер приема / отправки UDP-буфера, не могли бы вы подробно рассказать, как? Важно, чтобы на сервере вы изменили и rmem_max, и rmem_default, например: sysctl -w net.core.rmem_max=524287 sysctl -w net.core.wmem_max=524287 sysctl -w net.core.rmem_default=524287 sysctl -w net.core.wmem_default=524287

Тестирование ваших настроек

Остановите statsd и приложение узла, затем в режиме ожидания системы используйте iperf для проверки скорости передачи пакетов, которую может обработать сеть / ядро. Если вы можете передавать 40K пакетов / с с помощью iperf, но не можете с помощью statsd, тогда вам следует сосредоточить свои усилия на настройке statsd.

Другие переменные

Также не забудьте настроить net.core.netdev_max_backlog: максимальное количество пакетов, которые могут быть помещены в очередь, когда определенный интерфейс получает пакеты быстрее, чем ядро ​​может их обработать.

Другой способ ip_conntarck module, Вы уверены, что ваш linux-box может принять новое соединение? проверить через:

root@debian:/home/mohsen# sysctl net.ipv4.netfilter.ip_conntrack_max
net.ipv4.netfilter.ip_conntrack_max = 65536
root@debian:/home/mohsen# sysctl  net.ipv4.netfilter.ip_conntrack_count
net.ipv4.netfilter.ip_conntrack_count = 29

Вы должны проверить

net.ipv4.netfilter.ip_conntrack_max >  net.ipv4.netfilter.ip_conntrack_count

если max == count, ваше максимальное соединение заполнено, и ваш linux-box не может принять новое соединение.
Если у вас нет ip_conntrack, вы можете легко загрузить через modprobe ip_conntrack

Другие вопросы по тегам