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

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 со следующей настройкой:

Я уже проверил возможные причины:

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

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

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

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

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

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

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

Попробуйте использовать регулятор производительности и отключить любые функции энергосбережения в 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 модуль, вы уверены, что ваш 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-бокс не может принять новое соединение.
Если у вас нет ip_conntrack, вы можете легко загрузить через modprobe ip_conntrack