![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
В продолжение темы.
Итак, FreeBSD это конструктор, части которого требуют ручной доводки напильником, но результат получается хороший (см. ссылку выше). Тем, кого с души воротит от таких конструкторов, можно дальше не читать, а отправляться искать дистрибьютора Cisco, например.
1. Стабильность.
- Все релизы FreeBSD вплоть до 8.2-RELEASE включительно содержат races в ядре, которые с некоторой небольшой вероятностью приводят к панике при удалении системного интерфейса, что при использовании mpd случается часто. Нахождение и исправление этих проблем - заслуга Глеба Смирнова, который закоммитил исправления в 9-CURRENT и 8.2-STABLE в марте-апреле 2011-го (перед этим я несколько недель гонял патчи под нагрузкой). Поэтому, если важна стабильность - нужно обновляться до 8.2-STABLE или ждать 8.3-RELEASE.
Проблема проявляется не у всех. Если у вас не слишком большая нагрузка (скажем, до 500 одновременных сессий), то роутер и без этих исправлений может работать многими неделями, не паникуя. А при количестве сессий около 1000 мои роутеры паниковали каждый через пару-тройку дней, то есть почти каждый день который-нибудь да падал. Но с упомянутыми фиксами уже много недель всё стабильно. - Кроме указанных выше (исправленных) проблем, в ядре 8.2 есть и другой потенциальный источник нестабильности. Начиная с релиза 8.0, система поддерживает автоматическое ровное распределение входящей сетевой нагрузки по нескольким процессорным ядрам следующим образом: при поступлении пакетов из сетевой карты драйвер карты может укладывать пакеты в системную очередь netisr и на этом завершать свою работу с этим пакетом, а затем из очереди пакеты выбирают несколько ядерных тредов (по одному на ядро или меньше, это настраивается) и обрабатывают пакеты (маршрутизация и прочее) уже параллельно.
При старом же поведении системы вся обработка пакета выполняется тем ядром, которое обработало первоначальное прерывание при получении данных драйвером сетевой карты, и, если драйвер использует только один вектор прерывания (абсолютное большинство случаев при обработке трафика PPPoE/PPtP на сегодняшний день), то лишь одно ядро CPU и будет загружено обработкой входящего с этой сетевой карты трафика, а остальные ядра могут оказаться сильно недогруженными. Старое поведение (прямая обработка пакетов) по-прежнему включено по умолчанию и его можно отключить, прямо во время работы выставив в ноль sysctl net.isr.direct (плюс дополнительно есть sysctl net.isr.direct_force, подробней они документированы в комментариях в файлеsrc/sys/net/netisr.c
).
Новое поведение действительно сильно помогает выровнять загрузку ядер, но пока использовать его без ущерба для стабильности можно лишь в серверах или маршрутизаторах, где набор системных интерфейсов фиксирован или почти фиксирован. При использовании же mpd для массового обслуживания регулярно происходит следующее: пакеты застаиваются в разнообразных системных очередях, начиная с самой netisr и далее по списку (шейперы и прочее) и после отключения абонента и удаления соответствующего сетевого интерфейса ядро достаёт из очереди пакет, имеющий ссылку на уже не существующий интерфейс, и при обработке такого пакета паникует из-за обращения к уже освобожденной памяти (или даже к вновь занятой совершенно другими данными). Эта алгоритмическая проблема носит название проблемы "dangling pointer" и является недостатком дизайна ядра. При старом поведении такого не происходит, поэтому при работе mpd и большом количестве постоянно подключающихся/отключающихся сессий отключать net.isr.direct пока нельзя, а для выравнивания загрузки CPU нужно использовать другие методы. - Необходимо сказать "прощай" архитектуре i386, даже если в вашем роутере менее 4GB памяти. Есть неоднократные свидетельства того, что рассмотренный ниже необходимый для повышения производительности тюнинг приводит к переполнениям каких-то ядерных структур и паникам. Деталей не знаю, потому как изначально использовал amd64 и по тем же свидетельствам, простая смена архитектуры убирает и эти паники. mpd-5.5 замечательно работает на amd64 и держаться за i386 на роутере нет никакого смысла.
- Тюнинг NETGRAPH.
При интенсивном подключении/отключении абонентов mpd-5.5 генерирует огромное количество сообщений для ядерной подсистемы NETGRAPH, создавая/удаляя необходимые ноды. Сообщения эти укладываются в очереди, длины которых можно задавать в loader.conf параметрами net.graph.maxdata и net.graph.maxalloc и состояние которых можно просматривать командой . Последний столбец в выводе этой команды показывает количество случаев, когда очереди эти переполнялись. mpd-5.5 пока не умеет справляться с переполнением, оставляя в ядре "мусор" в виде частично созданных структур, что ведет к неуспеху подключения абонента в момент переполнения очереди, но, главное, к периодическим неуспехам при создании новых подключений в будущем, даже когда очереди разгрузились.vmstat -z|egrep 'ITEM|NetGraph'
Например, массовое отключение пользователей в результате аварии на сети распределения может привести к лавине сообщений NETGRAPH от mpd и переполнению этих ядерных очередей, а потом пользователи не могут переподключиться из-за "мусора" в ядре (этот мусор можно удалить вручную через ngctl без перезагрузки). Обойти проблему можно, резко увеличив длины очередей так, чтобы даже в самые пиковые моменты они не переполнялись. Контролировать переполнение можно указанной выше командой vmstat. Пишем в /boot/loader.conf:# netgraph queue sizes tuning, see vmstat -z|egrep 'ITEM|NetGraph'
net.graph.maxdata=65536
net.graph.maxalloc=65536
Отдельное спасибо Александру Мотину за помощь в диагностике этой проблемы.
Продолжение следует.