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

Почему TCP accept () работает так плохо под Xen?

Скорость, с которой мой сервер может принимать () новые входящие TCP-соединения, очень низкая под Xen. Тот же тест на железе показывает увеличение скорости в 3-5 раз.

  1. Почему это так плохо под Xen?
  2. Можете ли вы настроить Xen для повышения производительности новых TCP-соединений?
  3. Существуют ли другие платформы виртуализации, лучше подходящие для такого рода сценариев использования?

Задний план

В последнее время я исследовал некоторые узкие места производительности собственного Java-сервера, работающего под Xen. Сервер говорит по протоколу HTTP и отвечает на простые вызовы TCP подключения / запроса / ответа / отключения.

Но даже при отправке трафика на сервер он не может принимать более 7000 TCP-соединений в секунду (на 8-ядерном экземпляре EC2, c1.xlarge с Xen). Во время теста сервер также демонстрирует странное поведение, когда одно ядро ​​(не обязательно ЦП 0) сильно загружается> 80%, в то время как другие ядра почти бездействуют. Это заставляет меня думать, что проблема связана с ядром / базовой виртуализацией.

При тестировании того же сценария на голой железной, не виртуализированной платформе, я получаю результаты тестов, показывающие, что скорость TCP accept () превышает 35 000 в секунду. Это на четырехъядерной машине Core i5 под управлением Ubuntu со всеми ядрами, почти полностью загруженными. Мне такая цифра кажется правильной.

На экземпляре Xen я снова попробовал включить / настроить почти все параметры, которые есть в sysctl.conf. Включая включение Управление приемом пакетов и Получение управления потоком и закрепление потоков / процессов на процессорах, но без видимого выигрыша.

Я знаю, что при работе с виртуализацией следует ожидать снижения производительности. Но до такой степени? Более медленный сервер без ОС, превосходящий по производительности virt. 8-ядерный в 5 раз?

  1. Это действительно ожидаемое поведение Xen?
  2. Можете ли вы настроить Xen для повышения производительности новых TCP-соединений?
  3. Существуют ли другие платформы виртуализации, лучше подходящие для такого рода сценариев использования?

Воспроизведение этого поведения

При дальнейшем исследовании и выявлении проблемы я обнаружил, что netperf Инструмент тестирования производительности может имитировать аналогичный сценарий, с которым я столкнулся. Используя тест TCP_CRR netperf, я собрал различные отчеты с разных серверов (как виртуализированных, так и не виртуальных). Если вы хотите поделиться некоторыми выводами или посмотреть мои текущие отчеты, см. https://gist.github.com/985475

Как я узнаю, что эта проблема не из-за плохо написанного программного обеспечения?

  1. Сервер был протестирован на «голом железе», и он почти полностью загружает все доступные ему ядра.
  2. При использовании TCP-соединений keep-alive проблема исчезает.

Почему это важно?

В ESN (мой работодатель) Я руководитель проекта Beaconpush, сервер Comet / Web Socket, написанный на Java. Несмотря на то, что он очень производительный и может насыщать практически любую предоставленную ему полосу пропускания в оптимальных условиях, он по-прежнему ограничен тем, насколько быстро могут быть установлены новые TCP-соединения. То есть, если у вас большой отток пользователей, когда пользователи приходят и уходят очень часто, придется устанавливать / разрывать многие TCP-соединения. Мы стараемся смягчить это, сохраняя соединения как можно дольше. Но, в конце концов, именно производительность accept () удерживает наши ядра от вращения, а нам это не нравится.


Обновление 1

Кто то опубликовал этот вопрос в Hacker News, там тоже есть вопросы / ответы. Но я постараюсь обновлять этот вопрос, используя информацию, которую я найду по ходу дела.

Оборудование / платформы, на которых я это тестировал:

Я нахожусь в процессе повторного запуска этих тестов и заполнения отчетов на https://gist.github.com/985475 Если вы хотите помочь, поделитесь своими числами. Это просто!

(План действий вынесен в отдельный сводный ответ)

Прямо сейчас: производительность малых пакетов под Xen - отстой

(вместо этого перенесен из самого вопроса в отдельный ответ)

По словам пользователя HN (разработчика KVM?), Это связано с небольшой производительностью пакетов в Xen, а также с KVM. Это известная проблема виртуализации, и, по его словам, ESX от VMWare справляется с ней намного лучше. Он также отметил, что KVM предлагает некоторые новые функции, призванные облегчить это (исходный пост).

Эта информация немного обескураживает, если она верна. В любом случае, я попробую описанные ниже шаги, пока какой-нибудь гуру Xen не даст окончательного ответа :)

Иэн Кей из списка рассылки xen-users составил этот график: Обратите внимание на столбцы TCP_CRR, сравните «2.6.18-239.9.1.el5» с «2.6.39 (с Xen 4.1.0)».

Текущий план действий на основе ответов здесь и от HN:

  1. Отправьте эту проблему в список рассылки Xen и bugzilla xensource, как это предлагает syneticon-dj. А сообщение было отправлено в список xen-пользователей, в ожидании ответа.

  2. Создайте простой патологический тестовый пример на уровне приложения и опубликуйте его.
    Создан тестовый сервер с инструкциями и опубликовано на GitHub. Благодаря этому вы сможете увидеть более реальный вариант использования по сравнению с netperf.

  3. Попробуйте использовать 32-битный гостевой экземпляр PV Xen, так как 64-битный может вызывать дополнительные накладные расходы в Xen. Кто-то упомянул об этом на HN. Не имело значения.

  4. Попробуйте включить net.ipv4.tcp_syncookies в sysctl.conf, как предлагает abofh на HN. Это очевидно мощь улучшить производительность, так как в ядре будет происходить рукопожатие. Мне с этим не повезло.

  5. Увеличьте отставание с 1024 до чего-то намного большего, что также предлагается abofh на HN. Это также может помочь, поскольку гость потенциально может принять () больше соединений во время выполнения фрагмента, заданного dom0 (хостом).

  6. Еще раз проверьте, что conntrack отключен на всех машинах, так как он может вдвое снизить скорость приема (предложено deubeulyou). Да, во всех тестах он был отключен.

  7. Проверьте "переполнение очереди прослушивания и переполнение сегментов синхронизации в netstat -s" (предложено mike_esspe на HN).

  8. Разделите обработку прерываний между несколькими ядрами (RPS / RFS, которые я пытался включить ранее, должны делать это, но, возможно, стоит попробовать еще раз). Предложено adamt в HN.

  9. Отключение разгрузки сегментации TCP и ускорения разброса / сбора в соответствии с предложением Мэтта Бейли. (Невозможно на EC2 или подобных хостах VPS)

Как ни странно, я обнаружил, что отключение аппаратного ускорения сетевого адаптера значительно улучшает производительность сети на контроллере Xen (также верно для LXC):

Ускорение разброса-сбора:

/usr/sbin/ethtool -K br0 sg off

Разгрузка сегментации TCP:

/usr/sbin/ethtool -K br0 tso off

Где br0 - ваш мост или сетевое устройство на хосте гипервизора. Вам нужно будет настроить это так, чтобы выключать его при каждой загрузке. YMMV.

Может быть, вы могли бы немного уточнить - вы запускали тесты под Xen на своем собственном сервере или только на экземпляре EC2?

Accept - это просто еще один системный вызов, а новые соединения отличаются только тем, что первые несколько пакетов будут иметь некоторые специфические флаги - гипервизор, такой как Xen, определенно не должен видеть никакой разницы. Другие части вашей установки могут: например, в EC2, я не удивлюсь, если группы безопасности имеют к этому какое-то отношение; Conntrack также сообщается о сокращении вдвое скорости приема новых подключений (PDF).

Наконец, похоже, что есть комбинации ЦП / Ядро, которые вызывают странное использование ЦП / зависание на EC2 (и, вероятно, Xen в целом), поскольку недавно опубликовал в блоге Librato.

Убедитесь, что вы отключили iptables и другие хуки в коде моста в dom0. Очевидно, это применимо только к настройке Xen в сети моста.

echo 0 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 0 > /proc/sys/net/bridge.bridge-nf-call-arptables

Это зависит от размера сервера, но на меньших (4-ядерный процессор) выделите одно ядро ​​процессора для Xen dom0 и закрепите его. Варианты загрузки гипервизора:

dom0_max_vcpus=1 dom0_vcpus_pin dom0_mem=<at least 512M>

Вы пытались передать физическое устройство Ethernet PCI на domU? Должен быть хороший прирост производительности.