Принцип делить все и вся существует столько, сколько миллиардов лет существует Вселенная. Чаще всего объекты делятся в одинаковых пропорциях и неравный отхваченный кусок кем или чем-либо вызывает недовольство поделенных. Подобные ситуации часто возникают тогда, когда объект деления имеет весомое значение в системе. Перенесемся в 21 век. Наблюдая процессы в обществе и, в первую очередь в информационной сфере, можно заметить, что разумно делить все-таки научились. И, порой алгоритмы настолько неподдельны и устойчивы, что не оставляют никакой возможности взять больше или меньше дозволенного. Применив все вышеизложенное к передаче данных можно понять о чем идет речь.
Bursts
Часто возникает необходимость выдать так называемую пиковую скорость клиенту на определенный промежуток времени. К примеру, иногда требуется ускорить загрузку страниц, оставив при этом среднюю скорость на закачку файлов не выше отведенной. Или нужно редко посылать запросы и принимать данные, но делать это с максимальной скоростью. Глупо было бы в таком случае выдавать клиенту большую скорость, так как в один прекрасный момент из-за неосторожности или злого умысла остальные пользователи могут остаться или вовсе без Интернета, или получать его не таким, каких хотелось и за сколько заплачено.
Разработчики Mikrotik предоставили в распоряжение все необходимые инструменты для управления описанной выше пиковой скоростью. Следующие параметры характеризуют ее поведение:
- burst-limit - скорость, которая будет доступна сразу при подключении;
- burst-threshold – средняя скорость за последние burst-time секунд;
- burst-time - время для подсчета burst-threshold.
Момент, когда клиенту или классу нужно выдать максимальную скорость, определяется следующим образом. Раз в 1/16 времени burst-time вычисляется загрузка канала на указанное число секунд. Если средняя загрузка составила менее burst-threshold, то клиенту или классу выделяется указанная в burst-limit скорость до тех пор, пока она не превысит burst-threshold. После этого действует ограничение max-limit до тех пор, пока снова не случится понижение скорости менее burst-threshold.
Установим следующие параметры limit-at=128000/128000, max-limit=256000/256000, burst-limit=512000/512000, burst-treshold=192000/192000, burst-time=8, и понаблюдаем что случится с графиком загрузки канала от одного клиента:
Данный график характерен для случая с закачкой большого файла по протоколу http. После первой секунды средняя загрузка канала будет равна (0+0+0+0+0+0+0+512)/8=64 kbps, что менее установленного нами параметра burst-threshold. После второй секунды средняя скорость будет равна (0+0+0+0+0+0+512+512)/8=128kbps. После третьей секунды средняя скорость превысит показатель burst-threshold. В этот момент скорость резко упадет до значения параметра max-limit и будет держаться на этом уровне до тех пор, пока средняя загрузка канала не станет меньше burst-threshold и снова не произойдет выдача burst скорости.
Schedulers
Рассмотрим алгоритмы так называемых Schedulers, о которых упоминалось выше. Обычно они применяются вкупе с шейперами, однако некоторые из них так же обладают функциями ограничения скорости. Физически Scheduler предшествует шейперу и представляет ему уже подготовленные очереди пакетов, к которым следует применять ограниения.
PFIFO/BFIFO
Packet/Bytes (FIFO) алгоритм, основанный на принципе первый пришел-первый ушел. Используется для ethernet-интерфейсов. Единственный параметр, используемвый для конфигурирования данного алгоритма, - это pfifo-limit (bfifo-limit). Он указывает на количество байт, которые могут храниться в выходном буфере. Не попавшие в буфер пакеты будут разрушаться. Графически алгоритм можно изобразить с помощью следующей схемы. По сути дела PFIFO/BFIFO ничего особенного из себя не представляет и никаких приемуществ не дает. Он просто есть и используется там, где его использовать целесообразно…
SFQ
SFQ (Stochastic Fairness Queuing) – этот алгоритм можно назвать "случайно-честным". Он применятся тогда, когда требуется предоставить всем TCP/UDP-подключениям одинаковую возможность по передаче данных. Для конфигурирования SFQ используется два параметра:
- sfq-perturb – указывает через какое время нужно менять хэширующий алгоритм, который определяет как будут формироваться под-очередь запросов;
- pcq-allot – определяет количество байт в под-очереди.
SFQ работает по следующему принципу: алгоритм изымания пакетов из под-очередей одновременно выпускает в выходной интерфейс pcq-allot количество байт, а хэширующий алгоритм добавляет к каждый под-очереди pcq-allot байт, сохраняя при этом равновесие и одинаковую длину всех подочередей. Схему работы SFQ можно сравнить с мясорубкой, в которой через выходную решетку одновременно изо всех дырок в одинаковом количестве выходит фарш :).
Алгоритм SFQ рекомендуется использовать в случаях, когда канал сильно загружен и необходимо предоставить приложениям одинаковую возможность по передаче данных. Единственным его недостатком является то, что одно приложение, открыв много потоков, может заглушить остальные подключения.
PCQ
PCQ (Per Connection Queuing) является частным случаем SFQ за тем исключением, что формирование потоков в под-очереди будет происходить в соответствии с неким правилом. Это может быть адрес источника/получателя и порт источника/получателя. Таким образом можно равномерно распределить скорость между участниками вне зависимости от количества открытых подключений. Алгоритм предоставляет следующие параметры для конфигурирования:
- pcq-classifier – параметр для формирования очередей. Может принимать следующие значения:
- src-address – параметром для группировки в субочереди служит адрес источника;
- src-port – параметром для группировки в субочереди служит порт источника;
- dst-address – параметром для группировки в субочереди является адрес назначения;
- dst-port – параметром для группировки в субочереди служит порт получателя.
- pcq-rate – число, которое указывает в какой пропорции разделять трафик по очередям. По-умолчанию 0.
- pcq-limit – длина под-очереди;
- pcq-total-limit - общее количество пакетов во всех очередях.
Данный алгоритм является основным при необходимости разделить пропускную способность поровну между классами или клиентами. С его помощью можно организовать динамический шейпинг, о котором много где говорят, но толковая реализация автору ещё не встречалась ни в одном продукте.
Классифицировав под-очереди по адресу источника мы получим отдельную очередь для каждого адреса, соответственно количество потоков с одного адреса не будет играть роли при доступе к выходному интерфейсу.
Стоит отметить гибкость такой классификации. Применив ее по источнику к внешнему интерфейсу, в под-очереди будут попадать внешние адреса, так как в этом случае параметр src-address будет все равно содержать адрес, являющийся источником передачи данных. Применив эту же классификацию к внутреннему интерфейсу, в очереди попадут адреса клиентов или классов. Таким образом задав два правила, отличающиеся одним параметром, можно разделить поровну как входящий так и исходящий каналы.
RED
RED (Random Early Detection) – алгоритм, призванный выравнивать пропускную способность и сглаживать скачки, контролируя средний размер очереди. Когда ее размер достигает значения red-min-threshold алгоритм удаляет случайно выбранный пакет. Число удаленных пакетов растет с увеличением среднегого размера очереди. Если размер достигает значения red-max-threshold все пакеты удаляются. Однако случаются ситуации, когда реальный размер очереди (не средний) значительно больше red-max-threshold. В таком случае все пакеты, выходящие за рамки предела red-limit, удаляются.
Использование алгоритма крайне не желательно при присутствии UDP-трафика, так как в связи с неразборчивостью алгоритма при удалении пакетов из очереди и принципом работы UDP-протокола, данные могут не дойти до получателя.
От теории к практике
Сейчас мы знаем все необходимое для того, чтобы построить необходимые нам правила. Так как на практике применение алгоритмов SFQ и RED используется крайне редко, то на примерах их работы мы останавливаться не будем.
Queue Trees
Queue Trees - особый тип очередей, который прямо отражает устройство шейпера HTB. Он позволяет строить деревья правил (классов) и на самом низком уровне управлять пакетами.
Вкратце объясним значение основных элементов управления, присутствующих в Queue Trees:
- burst-limit (целое) – максимальная burst-скорость;
- burst-threshold (целое) – средняя загрузка канала, при которой разрешено выдать burst-limit;
- burst-time (время) – используется для подсчета средней загрузки канала;
- flow (text) – поток, маркированный в /ip firewall mangle;
- limit-at (целое) – гарантированная скорость;
- max-limit (целое) – максимальная скорость;
- name (text) – имя очереди;
- parent (text) – родитель в иерархии классов HTB;
- priority (целое: 1..8) – приоритет очереди;
- queue (text) – тип очереди. Задается в /queue type.