
Я провожу ряд нагрузочных тестов, чтобы определить производительность следующей конфигурации:
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.60GHz
- 2 ГБ ОЗУ
- Убунту 14.04 x86_64
Что я уже проверил на предмет возможных причин:
- Увеличение размера приема/отправки буфера UDP.
- Нагрузка на ЦП, влияющая на тест. (макс. нагрузка 40-50%, как на стороне клиента, так и на стороне сервера)
- Запуск tcpdump на определенных интерфейсах вместо «любых».
- Запуск tcpdump с опцией «-p» отключает беспорядочный режим.
- Запуск tcpdump только на сервере. Это привело к потере 20% пакетов и, похоже, не повлияло на тесты.
- Запуск tcpdump только на клиенте. Это привело к повышению производительности.
- Увеличил netdev_max_backlog и netdev_budget до 2^32-1. Это не дало результата.
- Пробовал все возможные настройки неразборчивого режима на каждой сетевой карте (сервер включен, а клиент выключен, сервер выключен, а клиент включен, оба включены, оба выключены). Это не дало результата.
решение1
Когда tcpdump запущен, он будет довольно быстро читать входящие кадры. Моя гипотеза заключается в том, что настройки буфера кольца пакетов сетевой карты могут быть немного маленького размера; когда tcpdump запущен, он очищается более своевременно.
Если вы являетесь подписчиком Red Hat, то эта статья поддержки будет вам очень полезна.Обзор приема пакетов. Там есть некоторые вещи, которые, как мне кажется, вы еще не рассматривали.
Подумайте, как ваша система обрабатывает IRQ; рассмотрите возможность увеличения «dev_weight» сетевого интерфейса (что означает больше пакетов, считываемых с сетевой карты в пространство пользователя); посмотрите, как часто приложение считывает сокет (может ли оно использовать выделенный поток, существуют ли известные проблемы/обходные пути относительно масштабируемости).
Увеличьте буфер кадра сетевой карты (используя ethtool
команду -- посмотрите на --set-ring
аргументы и т. д.).
Обратите внимание на «масштабирование на стороне приема» и используйте по крайней мере столько потоков приема, чтобы считывать трафик.
Интересно, делает ли tcpdump что-нибудь интересное, например, использует ли он поддержку ядра длябуферы кольца пакетов. Это помогло бы объяснить наблюдаемое вами поведение.
решение2
Какой регулятор мощности вы используете? Я видел похожее поведение с регулятором "ondemand" или "conservative".
Попробуйте использовать регулятор «производительности» и отключить все функции энергосбережения в BIOS сервера.
Это что-то меняет?
решение3
Другой способ — ip_conntarck
модуль. Вы уверены, что ваш Linux-бокс может принять новое соединение? Тест через:
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
решение4
Я подозреваю, что принимающая сторона просто не способна справиться с такой скоростью передачи пакетов, и вот почему:
с помощью tcpdumpна клиентеуменьшает количество потерянных пакетов: tcpdump замедляет клиента, и поэтому сервер видит гораздо более низкую скорость упаковщика, с которой он все еще может частично справиться. Вы должны быть в состоянии подтвердить эту гипотезу, проверив счетчики пакетов RX/TX как на клиенте, так и на сервере
Вы упомянули, что увеличили размер приема/отправки буфера 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для проверки скорости передачи пакетов, которую может обработать сеть/ядро. Если вы можете передавать 40 тыс. пакетов/с с помощью iperf, но не можете с помощью statsd, то вам следует сосредоточить свои усилия на настройке statsd.
Другие настройки
Также не забудьте настроитьnet.core.netdev_max_backlog: максимальное количество пакетов, разрешенных для постановки в очередь, когда определенный интерфейс получает пакеты быстрее, чем ядро может их обработать.