Я запускаю набор нагрузочных тестов, чтобы определить производительность следующей настройки:
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 сервера.
Это что-то меняет?
Я подозреваю, что принимающая сторона просто не способна обрабатывать скорость передачи пакетов, и вот почему:
используя 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 для проверки скорости передачи пакетов, которую может обрабатывать сеть / ядро. Если вы можете передавать 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