Pull to refresh

Linux под нагрузкой. Высокопроизводительный шейпер

Reading time 5 min
Views 13K
В прошлой заметке мы рассматривали некоторые аспекты тюнинга роутера под Linux, предназначенного для работы в условиях высоких нагрузок: Linux под нагрузкой. Маршрутизатор, NAT-сервер Теперь же речь пойдет о шейперах.

Ограничение скорости прохождения трафика (шейпинг) является достаточно ресурсоемкой задачей. Поэтому, при наличии в сети хотябы нескольких сотен абонентов, и при наличии больших объемов проходящего трафика, вопрос оптимизации шейперов встает особенно остро.

Рассматривать будем шейпер под управлением Linux: эта ОС показала наилучшие результаты по производительности в условиях высоких нагрузок.

Короткое введение



Шейпер — дисциплина обслуживания очереди пакетов. Дисциплина может быть с классами и без оных. С классами — значит, что трафик может быть “зашейпен” в соответствии с определенным классом.

Какой трафик каким классом шейпится – определяет фильтр.

Говоря проще, имеем два дерева: дерево фильтров и дерево классов. Фильтры раскидывают по определеным критериям трафик на классы. В классах трафик приоретизируется или шейпится в соответствии с заданными в классах параметрами.

С хешами и без хешей



Как любое дерево, дерево фильтров становится слишком ресурсо-затратным при достижении определенного порога.

Когда пакет от какого-то IP-адреса попадает на дерево фильтров, он начинает сравниваться с критериями каждого фильтра. При совпадении, пакет отправляется в соответствующий класс. Т.е. для каждого пришедшего пакета производится последовательно проверка на предмет соответствия критерию каждого фильтра в дереве до тех пор, пока не произойдет совпадение.

Например, для сети по 24-й маске у нас будет в среднем 128 шагов для каждого пакета при поиске нужного для него класса.

Это несущественно при небольших объемах трафика и при небольшом кол-ве абонентов. Когда же абонентов десятки тысяч, а в интернет уходят гигабиты, такой подход становится просто невозможным – сервер шейпинга банально не будет справляться с нагрузкой.

Если все дерево – это последовательность проверок на IP-адрес, то гораздо эффективнее будет задействовать хеши. Хеш — это таблица соответствий неких “значений” неким “ключам”. В нашем случае ключеом выступает IP-адрес, а значением – фильтр, направляющий пакет в свой класс.

Таким образом, по ключу (IP-адресу) мы быстро находим нужный фильтр для пакета, – в 1 шаг.

Собственно, про использование хешей статей уже написано немало – это не является “чем-то военным”. Можно обратиться к первоисточнику.

Скрипт для построения шейпера



Сильно облегчить жизнь при построении шейперов может вот такой вот Fast U32 hashing filter generator – это программа на Си, написанная румынским (?) сисадмином.

На вход ей даются следующие параметры:

  • prefix.in – список префиксов и соответствующих им классов в формате <префикс> <класс>
  • u32filters.out – выходной файл, сюда будут сохраняться фильтры
  • interface – имя интерфейса, на котором будет строиться шейпер
  • src/dst – направление потока (входящий или исходящий)
  • batch – если этот параметр указан, выходной файл будет генерироваться пригодным для запуска tc –b


Подробные примеры можно посмотреть на странице проекта выше.

Строго говоря, вам не нужно особенно глубоко вникать в суть работы данной программы – в данном случае вам не придется иметь с ней дело.

Для удобства я написал небольшой скрипт, который на основе заданной конфигурации строит таблицы префиксов и классов, запускает упомянутую выше программу для построения фильтров с нужными параметрами, из всего имеющегося добра строит готовую конфигурацию шейпера и запускает его через tc –b.

Все что требуется – указать некоторые конфигурационные параметры в файле.

Конфигурация скрипта



В папке скрипта есть следующие папки и файлы:

  • data – здесь будут располагаться промежуточные результаты работы скрипта, а так же конечная конфигурация шейпера: _classes – готовый конфиг шейпера, _filters – фильтры с хешами, _prefixes – таблица соответствий префиксов классам, _speeds – соответствие классов скоростям
  • lib – необходимые для работы библиотеки
  • log – логирование событий при работе скрипта
  • pid – здесь лежит pid процесса для предотвращения одновременного запуска нескольких копий скрипта
  • config – основной файл конфигурации скрипта
  • networks – список сетей, к которым необходимо строить шейперы
  • prefixtree.c – исходник построителя фильтров с хешами
  • shaper.php – сам скрипт шейпера


Вся конфигурация скрипта лежит в файле config. Для настройки надо обязательно под себя поменять следующие параметры:

  • в начале конфига параметры подключения к БД для забора IP-адресов и параметров скорости
  • DEV – интерфейс, на котором строить шейпер
  • DIR – направление потока трафика по отношению к абонентам: может быть in или out (входящий и исходящий соответственно)


Остальное менять не нужно.

В файле networks можно описать сети, для которых надо строить шейперы. Если файл пуст – шейперы будут строиться для всех абонентов.

IP-адреса абонентов выбираются из БД в MySQL.

Таблица shapers:

  • shaper_id – уникальный идентификатор абонента
  • id – идентификатор шейпера


Таблица cl_status:

  • ip – IP-адрес абонента
  • shaper_id – уникальный идентификатор абонента
  • status – состояние абонента (3 – вкл)
  • sin – скорость входящая
  • sout – скорость исходящая


Скорее всего, проще будет адаптировать запрос выборки IP-адресов абонентов под вашу конкретную БД, чем наоборот. Для этого нужно соответствующим образом поправить запрос в 70-й строке файла shaper.php

Компилирование prefixrtee.c



Для работы скрипта необходимо откомпилировать прилагающийся файл prefixtree.c

Делается это командой: gcc prefixtree.c –o prefixtree

Хочу заметить, что вместе с данным скриптом прилагается слегка исправленный вариант prefixtree, адаптированный для такого использования.

Запуск скрипта



После того как вы внесли соответствующие изменения в config, разобрались с select’ами в shaper.php, откомпилировали prefixtree.c, внесли (если необходимо) нужные сети в networks – можно запускать скрипт.

Запуск должен производиться из-под root, и заключается он просто в:

/usr/bin/php –q shaper.php

После этого скрипт:

  • прочитает config
  • прочитает networks
  • сделает необходимую выборку из БД для каждого IP (на основе networks)
  • создаст файл data/_prefixes
  • создаст файл data/_speeds
  • запустит prefixtree на исполнение, который создаст файл data/_filters
  • создаст файл data/_classes
  • запустит tc –b data/_classes


В результате чего будет построен и запущен шейпер на заданном интерфейсе по заданным параметрам для заданных IP-адресов.

Если у абонента несколько IP-адресов – будет построен один класс с заданным параметром скорости и все IP-адреса абонента будут направлены в этот класс. Таким образом, если у абонента несколько IP, будет создан один “канал” заданной скорости, который будет делиться между его IP.

Результирующая конфигурация шейпера будет лежать в data/_classes – это готовый файл конфига, который можно скармливать tc с опций batch (-b).

Логи



Все этапы работы скрипта отражаются в логах – папка log.

Статистика



Подобный шейпер успешно обслуживает более 5 тысяч абонентов.

Примечания



Конкретные значения полос пропускания и параметры htb в файле shaper.php необходимо будет править в каждом конкретном случае.

Скачать скрипт



Поскольку кода слишком много, чтобы приводить его здесь целиком, скачать скрипт можно на его домашней странице
Tags:
Hubs:
+42
Comments 70
Comments Comments 70

Articles