Как стать автором
Обновить

Базовые принципы полисеров и шейперов

Время на прочтение 11 мин
Количество просмотров 22K
Одними из инструментов обеспечения качества обслуживания в сетях передачи данных являются механизмы полисинга и шейпинга и, может быть, это самые часто используемые инструменты. Ваш Интернет провайдер, наверняка, ограничил вам скорость именно этим.

Тема качества обслуживания не самая простая для понимания, а если вы когда-нибудь интересовались именно полисерами и шейперами, то скорее всего встречали однотипные графики, отображающие зависимость скорости от времени, слышали термины «корзина», «токены» и «burst», может быть даже видели формулы для расчёта каких-то параметров. Хороший и типичный пример есть в СДСМ — глава про QoS и ограничение скорости.

В этой статье попробуем зайти чуть с другой стороны, опираясь на учебник Cisco, RFC 2697 и RFC 2698 — самые базовые понятия.

Первое в чём надо разобраться и на чём строится весь механизм управления скоростью — это понятие самой скорости. Скорость — величина производная, вычисляемая, нигде и ни в каком месте мы не видим её напрямую. Устройства оперируют только данными и их количеством. Про скорость мы говорим в контексте наблюдения и мониторинга, зная объём переданных данных за 5 минут или за 5 секунд и получая разные значения средней скорости.

Второе, количество данных пропускаемое интерфейсом за отрезок времени — константа, абсолют. Его нельзя ни уменьшить ни увеличить. Через 100Мбит/c интерфейс 90Мбит будут пропущены всегда за 0,9 секунды, а оставшуюся 0,1 секунду интерфейс будет простаивать. Но с учётом того что скорость вычисляемое значение, получим что данные были переданы со средней скоростью 90Мбит/c. Это мало похоже на дорожный трафик, у нас всегда либо 100% загруженность, либо полный простой. В контексте сетевого трафика, загруженность интерфейса — это сколько свободных промежутков времени у него остаётся из общего измеряемого интервала. Дальше продолжим употреблять размерность Мбит и секунды, для лучшего понимания, хотя это и не имеет никакого значения.

Отсюда вытекает основная задача и способ ограничения пропуска трафика — передать не больше заданного количества данных за единицу времени. Если у нас есть 100Мбит, а мы хотим ограничить скорость 50Мбит/c, то за эту секунду нам надо передать не больше 50Мбит, а оставшиеся данные передать в следующую секунду. При этом у нас есть только один способ это сделать — включить интерфейс, который всегда работает с постоянной скоростью, или выключить его. Выбор только в том, как часто мы будем включать и выключать.

Burst


Посмотрим на график скорости из учебника 5 класса по физике. Здесь показана зависимость объёма переданных данных по оси Y, от времени по оси X. Чем круче наклон прямой, тем больше скорость. Передать 50Мбит за секунду можно разными способами:



  1. Передать всё сразу за 0,5 секунды, а потом ждать следующей (зелёная сплошная)
  2. Передавать чаще, делая меньшие паузы, но увеличив их количество

Это приводит нас к понятию burst — максимальный непрерывно передаваемый объём данных, как правило он измеряется в байтах, а не в битах как у нас для простоты. Burst неразрывно связан со временем, чем он больше, тем длиннее пауза между передачей данных: Burst = Time Interval * CIR, где CIR, Committed Information Rate — ограничение по скорости которое мы вводим (красные точки) и эта величина, обычно, измеряется в битах в секунду.

Если burst=50, CIR=50Мбит/c, то время равно 1 секунде: Time Interval = Burst / CIR = 50/50. Значит каждую секунду, мы можем передать не больше 50Мбит. Так как скорость интерфейса у нас 100Мбит/c, то 50Мбит будут переданы за 0,5 секунды, оставшееся время будет простой. Начиная со следующей секунды у нас опять будет возможность передать 50Мбит.

В случае burst=25, получим 25/50 или 0,5 секунды между передачей каждых 25Мбит. С учётом скорости интерфейса на передачу 25Мбит будет затрачено 25/100=0,25 секунды и следующие 0,25 секунды интерфейс будет простаивать. В каждом случае мы 1/2 = CIR / Interface rate времени тратим на передачу и 1/2 на простой. Если увеличить CIR до 75Мбит/c, то соответственно 75/100=3/4 периода займёт передача и 1/4 пауза.

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

В большинстве случаев при конфигурации оборудования используются именно burst, хотя могут использоваться и временные интервалы. На графике хорошо видны отличия, меньший burst даёт более строгое следование заданному ограничению — график не убегает далеко от СIR, даже на меньшем измеряемом промежутке и при этом обеспечивает короткие паузы между моментами передачи. А больший burst не ограничивает трафик на коротких отрезках. Если измерять скорость только за первые 0,5 секунды, то получилось бы 50/0,5 = 100Мбит/c. А долгая пауза после такой передачи может негативно сказаться на механизмах управления трафиком за границами нашего устройства, или привести к потере логического соединения.

Если быть ближе к реальности, сетевой трафик, как правило, не передаётся непрерывно, а имеет разную интенсивность в разные моменты времени (зелёный пунктир):



На этом графике видно, что за 1 секунду мы хотим передать 55Мбит при ограничении 50Мбит. То есть, реальный трафик практически не выходит за границы которые мы установили к концу измеряемого интервала. При этом механизмы ограничения приводят к тому, что передаётся меньший объём данных чем мы ожидаем. И здесь больший burst выглядит лучше, так как захватываются интервалы где трафик действительно передаётся, а меньший burst и желание строго ограничивать трафик на всём участке, выливается в большие потери.

Шейпер


Будем ещё ближе к реальности, в которой всегда имеется буфер для передачи данных. С учётом того что интерфейс у нас или занят на 100% или простаивает, а данные могут поступать одновременно из нескольких источников быстрее чем интерфейс может их передавать, то даже простейший буфер формирует очередь, позволяя данным дождаться момента передачи. Он также позволяет компенсировать те потери которые у нас могут возникнуть из-за введённых ограничений:



Policer это график Burst 5 с предыдущего изображения. Shaper тот же график Burst 5, но с учётом буфера, в котором задерживаются не успевшие передаться данные и которые могут быть переданы чуть позже.

В результате, мы полностью обеспечили наши требования по ограничению трафика «сгладив» пики источника и не потеряв данные. Трафик по-прежнему имеет пульсирующую форму: чередующиеся периоды передачи и паузы — потому что мы не можем повлиять на скорость интерфейса и управляем только объёмом передаваемых за раз данных. Это тот самый график сравнения шейпера и полисера из СДСМ QoS, но с другой стороны:



Какой ценой мы этого достигли? Ценой буфера, который не может быть бесконечным и который вносит задержку в передаче данных. Пик на графике буфера приходится на 15Мбит, это те данные которые теряются полисером, но задерживаются шейпером. При заданном ограничении 50Мбит/c — это 15/50=300 миллисекунд, что для многих сетевых приложений уже за гранью дозволенного.

А теперь посмотрим когда эта цена играет роль, достаточно лишь чуть большей интенсивности трафика — 60Мбит/c, при ограничении 50Мбит/c:



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

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

Корзина


Для учёта объёма трафика переданного через интерфейс используется понятие и термин корзина. Фактически, это счётчик от максимального значения burst до 0, который уменьшается с передачей каждого кванта данных — токена. Соответственно, есть два процесса — один наполняет корзину, второй из неё забирает.

Корзина наполняется до величины burst каждый заданный интервал, при известном CIR. Для burst 5 и CIR 50, каждые 0,1 секунду, как было рассчитано чуть ранее. Но объём трафика за интервал времени может быть меньше чем заданный нами burst, так как условие ограничения — «не больше». Значит этот счётчик может не доходить до 0 и в корзине остаются токены. Тогда в следующий интервал, при заполнении корзины, неиспользуемый объём данных (токенов) будет потерян.

Такая ситуация видна на графике Policer выше, каждые 0,05 секунд мы в состоянии передать 5Мбит на скорости интерфейса, но количества данных которые у нас есть всего 3Мбит, так как скорость поступления данных всего 60Мбит/c. Именно поэтому график почти сливается с CIR, что не совсем корректно. Передача в любом случае осуществляется на скорости интерфейса и 3Мбит будут переданы за 0,03 секунды, а оставшиеся 0,02 будет пауза. Это давало бы нам характерную лесенку, которую мы видим на графике Shaper. Здесь, как раз, пример средней скорости и сглаживания точности измерения, что обычно показывают системы мониторинга оперирующие даже не секундами, а минутами.

Улучшим подход, зная что трафик спонтанен и больший burst может помочь не потерять данные. Введём ещё одну корзину, куда будем складывать неиспользованные на предыдущем интервале токены. Таким образом, в случае отсутствия трафика от источника, будет частично компенсироваться этот простой, как если бы у нас был больший burst. Для каждой корзины задаётся собственный burst, для основной — Committed Burst, CBS, Bc. А для второй — Excess Burst, EBS, Be. Таким образом максимальный объём данных который может быть непрерывно передан равен CBS+EBS.



Shaper Exs (жёлтый) — график с учётом двух корзин, каждая объёмом burst в 5Мбит. Shaper — график с предыдущего изображения. Теперь максимальный burst=EBS+CBS=10 и первые 0,1 секунду мы используем его. Основную корзину мы пополняем каждые 5/50=0,1 секунду. Соответственно, в момент времени 0,1 опять есть возможность передавать данные и период непрерывной передачи длится 0,15 секунды. В результате длительного простоя, когда трафика с источника не было и все данные из буфера мы передали, в момент времени 0,6 секунд, добавляем неиспользуемый объём данных во вторую корзину. Таким образом, получаем возможность снова вести непрерывный пропуск трафика в течение 0,15 секунд, что позволяет вовсе не использовать буфер. В итоге, получили удачный компромисс точности нарезки полосы, в случае интенсивного трафика, и лояльности в отношении всплесков при использовании большего burst.

Сделаем ещё одно улучшение касающееся времени. Избавимся от периодического процесса пополнения корзины и заменив его на пополнение только в те моменты, в которые к нам поступают данные. В большинстве случаев, меньше чем одним, целым пакетом за раз никто не оперирует. Поэтому можно посчитать период между приходами последовательных пакетов и пополнять корзину тем объёмом данных, которые соответствуют данному периоду. Это, во первых, исключит необходимость держать отдельный таймер для временных интервалов связанных с burst периодами, а во вторых, сократит периоды между возможными пропусками трафика.

Следовательно burst, как максимальный объём непрерывно передаваемых данных, отделился от понятия количество пополняемых за раз данных, хотя формула осталась та же: пополняемый объём в токенах = интервал между последовательными пакетами * CIR. Но пополнить корзину больше чем её максимальный объём burst мы не можем, это то условие с помощью которого и достигается ограничение. Размер пакета задаёт наименьший из возможных burst — размер наименьшего пакета в данной сетевой технологии. Если burst будет меньше, то целый пакет невозможно будет отправить за отведённый интервал, при заданной скорости интерфейса.

Полисер: 1 скорость, 2 корзины, 3 цвета


До этого речь шла, в основном, о шейперах, хотя понятия и термины аналогичны тем что применимы и для полисеров. Полисер, однако, как это определено в RFC 2697 это не механизм ограничения трафика, это механизм его классификации. Каждый проходящий пакет, в соответствии с заданным CIR, CBS и EBS относится к одной из категорий (цвету): conform (green), exceed (yellow), violate (red). На устройствах можно сразу настроить в каком случае трафик стоит блокировать, но в общем случае, это именно назначение метки или покраска.

Для каждого пакета происходит проверка по следующему алгоритму:

  1. Если размер пакета меньше чем токенов в первой корзине, то этот пакет помечается как green, а из первой корзины вычитается количество токенов соответствующих размеру пакета, иначе
  2. Если размер пакета меньше чем токенов во второй Excess корзине, то этот пакет помечается как yellow, а из второй корзины вычитается количество токенов соответствующих размеру пакета, иначе
  3. Пакет помечается как red и ничего и ниоткуда не вычитается.

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



Используем те же параметры что и раньше CIR=50, CBS=5, EBS=5. Количество токенов в корзинах теперь показано отдельно: основная Bucket C (голубой) и дополнительная Bucket E (фиолетовый). Теперь у нас не непрерывный поток битовых данных, а пакеты по 5Мбит. Что не совсем реально, трафик, в общем случае, состоит из разных по размеру пакетов приходящих в разные интервалы времени, и это очень сильно может изменить картину происходящего. Но для демонстрации базовых принципов и удобства подсчёта используем такой вариант. Также, отражён процесс пополнения корзины с приходом каждого пакета.

В первые 0,05 секунд передаём пакет в 5Мбит, опустошая основную корзину. С приходом второго пакета мы пополняем её, но на величину 2,5Мбит, что соответствует заданному CIR 0,05*50. Этих токенов не хватает для передачи следующего пакета в 5Мбит, поэтому мы опустошаем вторую корзину, но пакет помечается по другому. Через 0,05 секунд опять приходит пакет, и мы опять пополняем основную корзину на 2,5Мбит и этого объёма хватает для его передачи в зелёной категории. Следующему пакету, несмотря на то что корзина пополняется, уже не хватает токенов и он попадает в красную категорию. Красный сплошной график отражает ситуацию, если отбрасываются только пакеты помеченные красным.

Во время простоя корзины не пополняются, как это было видно на предыдущем графике, но в момент времени 0,6, при получении следующей порции данных высчитывается интервал между пакетами: 0,6-0,3=0,3 секунды, следовательно у нас есть 0,3*50=15Мбит для того чтобы пополнить основную корзину. Максимальный её объём CBS=5Мбит, остатком пополняется вторая корзина, тоже объёмом EBS=5Мбит. Оставшиеся 5Мбит мы не используем, тем самым трафик с очень длинными паузами всё равно ограничивается, чтобы не допустить ситуации: час бездействия — час без ограничений.

В итоге, на графике 6 зелёных участков или 30Мбит переданных за секунду — средняя скорость 30Мбит/c, что соответствует использованию только одной корзины и двух цветов. 3 жёлтых участка и в сумме с первым графиком 45Мбит/c, с учётом красных участков 55Мбит/c — две корзины, три цвета.

2 скорости, 3 цвета


Существует ещё один подход RFC 2698, в котором задаётся параметр пиковой скорости PIR — Peak Information Rate. И в этом случае используются две корзины, но каждая из которых заполняется независимо от другой — одна в соответствии с CIR, другая с PIR:

  1. Bucket CIR, пополняемый объём в токенах = интервал между последовательными пакетами * CIR
  2. Bucket PIR, пополняемый объём в токенах = интервал между последовательными пакетами * PIR

Таким образом, если PIR больше CIR то одна из корзин будет наполняться быстрее чем другая.

Трафик, как и в предыдущем случае, классифицируется на 3 категории следующим образом:

  1. Если размер пакета меньше чем токенов в CIR корзине, то этот пакет помечается как green и из обеих корзин вычитается количество токенов соответствующих размеру пакета, иначе
  2. Если размер пакета меньше чем токенов в PIR корзине, то этот пакет помечается как yellow и только из PIR корзины вычитается количество токенов соответствующих размеру пакета, иначе
  3. Пакет помечается как red и ничего и ниоткуда не вычитается.

Основная идея такого подхода использовать два независимых ограничения, если мы помещаемся в оба, то это зелёная зона, если только под одно, то жёлтая, если ни под одно, то красная.

Вспомним для чего нам вторая корзина и больший burst, чтобы компенсировать периоды простоя трафика за счёт менее строго ограничения за больший период. Подход с двумя условиями даёт нам ту же возможность. Сформируем PIR и CIR равными 50Мбит/c, размер первой корзины 5, а второй PBS 10. Почему 10? Потому что это независимое ограничение, что возвращает нас к самому первому графику показывающему разницу burst. То есть, мы хотим добиться среднего результата между burst 5 и burst 10 и задаём эти условия напрямую.



Получили такой же график для полисера, что и при использовании предыдущего метода. При burst=10 получаем больше свободы, а вторым условием burst=5 добавляем точности. Обратите внимание как ведут себя корзины, каждая сама по себе.

Два отдельных условия, каждое из которых выполняется для одних и тех же входящих значений. Более строгое — классифицирует трафик, который гарантированно попадает под него, а менее строгое расширяет эти границы. В случае равных CIR и PIR, получаем взаимозаменяемый с предыдущим метод.

А устанавливая PIR скорость увеличиваем количество степеней свободы. Можно отдельно проверить разные burst при разных профилях трафика с разными CIR, а потом совместить всё вместе с использованием этого метода:



CIR=50, PIR=75, CBS=5, PBS=7,5. CBS и PBS выбраны таким образом, чтобы укладываться в одинаковый интервал. Но, конечно, можно исходить из других условий, например для PIR сделать меньший burst, чтобы увеличить гарантию не выхода за обозначенные границы, а для CIR наоборот, более лояльный.

В принципе, при интенсивном трафике нет причин ставить маленький burst ни в каком случае, ни для какой из корзин. Несколько десятков секунд и несколько лишних мегабайт не сделают погоды на продолжительных временных интервалах, но частые блокировки из-за небольшого burst, могут сломать незаметные для нас механизмы регулировки потока. Для трафика 80Мбит/c, в зелёную зону уложилось 40Мбит/c. Учитывая жёлтую как раз вписались между CIR и PIR — 60МБит/c. Ещё раз, механизмы ограничения пытаются гарантировать не выход за верхние границы, про нижние они ничего не знают. И как видно в примерах, результирующий трафик всегда меньше заданных ограничений, иногда сильно меньше, даже если он сам попадал в них без посторонней помощи.

Описанные выше подходы сформировались в RFC уже больше 20 лет назад, но на свалку истории пока не торопятся, и часто применяются именно как ограничивающий инструмент ухудшающий качество, а не как классификатор, или как компенсирующий механизм. Даже в самых современных реализациях вы обязательно встретите если не эти алгоритмы, но эти термины обязательно и, конечно, сложность применения понятия скорости в сетях передачи данных. Может быть с ещё одной статьёй разобраться во всём этом станет чуть проще.
Теги:
Хабы:
+9
Комментарии 2
Комментарии Комментарии 2

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн