MAATRIX / Блог / BBR против CUBIC на реальных маршрутах: где смена алгоритма даёт плюс, а где минус

BBR против CUBIC на реальных маршрутах: где смена алгоритма даёт плюс, а где минус

MAATRIX

«Просто включите BBR, будет быстрее» — совет, который звучит правдоподобно и почти всегда неполон. BBR действительно решает реальную проблему CUBIC, но решает её не универсально: на одних маршрутах прирост заметен и стабилен, на других разница тонет в погрешности измерений, а на третьих BBR ведёт себя хуже, чем ожидалось, — особенно если канал не ваш личный, а общий с чужим трафиком. Разберём по сценариям, где смена алгоритма даёт реальный эффект, а где — нет.

Коротко о разнице в подходе

CUBIC — реактивный алгоритм: он наращивает окно перегрузки, пока не случится потеря пакета, и воспринимает саму потерю как единственный надёжный сигнал «канал переполнен». Проблема в том, что не всякая потеря вызвана переполнением — на беспроводных участках, спутниковых линках и некоторых шумных промежуточных сегментах пакеты пропадают из-за помех, а не из-за забитого буфера. CUBIC такие потери не отличает от настоящей перегрузки и одинаково режет окно в обоих случаях.

BBR (Bottleneck Bandwidth and Round-trip propagation time) вместо этого оценивает два физических параметра маршрута — пропускную способность узкого места и минимальную задержку без очередей — и старается держать в полёте ровно столько данных, сколько нужно, чтобы заполнить произведение этих величин (BDP), не опираясь на потерю как на основной триггер. Подробный разбор механики обоих алгоритмов, включая то, как именно BBR измеряет канал и почему CUBIC растит окно по кубической кривой, — в статье BBR против CUBIC: как TCP угадывает ширину канала. Здесь мы не повторяем эту механику, а разбираем, на каких реальных маршрутах разница между философиями действительно проявляется.

Сценарий 1: длинные высокоскоростные соединения на большие расстояния

Это тот случай, для которого BBR изначально и разрабатывался в Google. Чем длиннее маршрут и чем выше номинальная пропускная способность канала, тем больше произведение BDP — и тем дороже обходится каждая ошибка в оценке доступного окна. На межконтинентальном маршруте с RTT в сотню с лишним миллисекунд CUBIC-соединению нужно время, чтобы после каждого снижения окна снова разогнаться до прежней скорости, а кубическая кривая роста намеренно осторожничает рядом с точкой, где случилась предыдущая потеря. Пока окно ползёт вверх, часть пропускной способности канала простаивает впустую.

BBR в этой ситуации может держать канал загруженным более стабильно, потому что не привязывает объём данных в полёте к истории потерь на этом же соединении, а пересчитывает оценку BDP по факту измерений bandwidth и RTT. На маршрутах, где путь пакета вообще не совпадает с географическим расстоянием по прямой (это отдельная и частая причина завышенного RTT — разобрана в статье почему маршрут не совпадает с географией), длинный путь означает не только больший BDP, но и больше точек, где может случиться единичная не связанная с перегрузкой потеря — а значит преимущество BBR складывается сразу по двум причинам.

Важная оговорка: выигрыш здесь не гарантирован автоматически, а зависит от того, насколько канал вообще недоиспользован при CUBIC. Если узкое место маршрута — не TCP-окно, а физический потолок канала или ограничение на промежуточном оборудовании, смена алгоритма перегрузки ничего не изменит: разгонять там просто некуда. Прежде чем менять алгоритм ради длинного маршрута, стоит убедиться, что причина недобора скорости — именно в поведении congestion control, а не в размере окна приёма или физическом лимите; про это подробно — в статье про TCP-окно и длинный толстый канал.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Сценарий 2: каналы со случайными потерями не от перегрузки

Второй случай, где разница ощутима на практике, — маршруты, где потери случаются регулярно, но не потому, что кто-то забивает буфер. Классические примеры: беспроводные последние мили (Wi-Fi, мобильная связь, спутниковые каналы), а также дальние маршруты с шумными промежуточными сегментами, где случайная потеря 1–2 пакетов из тысячи — норма, а не признак перегрузки.

Именно на таких каналах хорошо видно, насколько дорого CUBIC платит за путаницу двух типов сигнала. В статье про потерю 0,3% пакетов, которая срезала скорость вдвое разобран конкретный механизм: даже небольшая доля случайных потерь заставляет реактивный алгоритм снижать окно так, будто канал перегружен, хотя фактическая доступная пропускная способность никуда не делась. BBR в теории устойчивее именно к этому классу потерь, потому что не привязывает решение «снижать темп» к каждому отдельному потерянному пакету, а опирается на собственную оценку канала, обновляемую по циклам зондирования.

Практическая проверка гипотезы на своём сервере не требует спутникового канала под рукой — потери можно смоделировать локально:

# добавить 1% случайных потерь на исходящем интерфейсе
tc qdisc add dev eth0 root netem loss 1%

# то же самое, но с корреляцией потерь (пачками, ближе к реальным помехам)
tc qdisc add dev eth0 root netem loss 1% 25%

# вернуть интерфейс в исходное состояние
tc qdisc del dev eth0 root

На таком стенде можно сравнить поведение CUBIC и BBR при одинаковом профиле потерь и увидеть разницу не в абстрактных процентах, а в конкретных ss -ti, показывающих текущее окно перегрузки, RTT и число повторных передач для активного соединения.

Сценарий 3: переполненный общий канал — где BBR может быть не лучше

Здесь начинается менее приятная часть разговора. Всё, что делает BBR полезным на своём собственном изолированном канале, устроено вокруг того, что BBR слабее реагирует на единичную потерю, чем CUBIC. Но если канал общий и на нём одновременно есть CUBIC-потоки других пользователей или сервисов, это же свойство превращается в проблему честности распределения полосы.

Классические реактивные алгоритмы вроде CUBIC исторически рассчитаны на сосуществование друг с другом: когда общий буфер узкого места переполняется, потерю получают приблизительно все конкурирующие потоки, каждый снижает окно, и в сумме получается более-менее справедливое разделение канала. BBR ориентируется не на факт потери, а на собственную оценку BDP — и на переполненном аплинке, где соседствуют BBR- и CUBIC-потоки, может не снижать темп отправки в той же мере, что и CUBIC-соседи, забирая себе непропорционально большую долю пропускной способности. Это была одна из главных тем публичной критики ранних ревизий BBR в сообществе сетевых инженеров, и более поздние доработки алгоритма были во многом направлены именно на улучшение честности сосуществования с классическими потоками — но насколько полно вопрос закрыт в конкретной версии ядра, которой вы пользуетесь, стоит проверять по актуальной документации, а не считать решённым раз и навсегда.

Практический вывод: если ваш сервер сидит на оверсабскрайбленном аплинке провайдера или в общем сегменте дата-центра, где полосу делят десятки чужих соединений, поведение BBR может заметно отличаться от того, что вы наблюдали в изолированном тесте между двумя своими серверами без посторонней конкуренции за канал. В изолированном тесте BBR обычно выглядит убедительно; на переполненном общем канале — не обязательно.

Сценарий 4: короткие соединения — где разница почти не видна

Есть и третий класс случаев, но уже не «BBR хуже», а «разница несущественна». Оба алгоритма — и CUBIC, и BBR — проходят через фазу разгона (slow start) в начале соединения, и на коротких по времени жизни TCP-сессиях — типичный HTTP-запрос, короткий API-вызов, небольшой файл — соединение часто просто не успевает выйти в ту фазу congestion avoidance, где различия философий вообще начинают проявляться. Для большинства сайтов и API с короткими запросами эффект от смены алгоритма перегрузки будет менее заметен, чем эффект от TLS session resumption, HTTP/2 или HTTP/3 мультиплексирования, качества CDN или банального размера ответа.

Это не значит, что алгоритм неважен в принципе — для долгоживущих соединений (потоковое видео, репликация базы данных, синхронизация больших объёмов файлов, бэкапы между дата-центрами) время в фазе congestion avoidance составляет большую часть жизни соединения, и там разница между алгоритмами накапливается. Но если ваша нагрузка — короткие запросы, ожидать драматического эффекта от смены алгоритма перегрузки не стоит.

Сводная таблица: когда менять смысл есть, а когда нет

Профиль маршрута / нагрузкиОжидаемый эффект от BBR
Длинный маршрут, высокий BDP, канал недоиспользован при CUBICПотенциально заметный плюс — стоит тестировать в первую очередь
Случайные потери не от перегрузки (Wi-Fi, спутник, шумный дальний сегмент)Потенциальный плюс, если именно потери, а не физический лимит, режут скорость
Общий переполненный канал с чужими CUBIC-потокамиНе гарантированный плюс — проверяйте честность распределения полосы отдельно
Короткие запросы (API, обычный веб-трафик)Разница обычно малозаметна на фоне других факторов
Стабильный внутренний канал дата-центра без конкуренцииРазница, как правило, невелика

Как тестировать на своём трафике, а не верить общим утверждениям

Главная практическая рекомендация здесь простая и одновременно самая нарушаемая: не переключайте алгоритм перегрузки на продакшене по умолчанию, опираясь на чужой отчёт «у нас BBR дал плюс X%». Профиль потерь, длина маршрута, степень оверсабскрайба канала и характер вашей нагрузки — у каждого сервиса свои, и универсальной цифры прироста, которая перенесётся на ваш случай без изменений, не существует.

Порядок проверки, который снижает риск ошибиться:

  1. Зафиксируйте текущий алгоритм и метрики baseline.
sysctl net.ipv4.tcp_congestion_control
sysctl net.ipv4.tcp_available_congestion_control

Снимите базовые показатели на реальной или максимально приближенной к реальной нагрузке: пропускную способность, распределение задержки (не только среднее, а перцентили), долю ретрансмиссий.

  1. Переключите алгоритм на тестовом сервере, не на проде.
modprobe tcp_bbr
sysctl -w net.core.default_qdisc=fq
sysctl -w net.ipv4.tcp_congestion_control=bbr

Связка с fq (fair queueing) как дисциплиной очереди важна — BBR проектировался и тестировался именно в паре с ней, и без неё поведение может отличаться от ожидаемого.

  1. Сравните на одинаковом профиле нагрузки, а не на синтетике в вакууме. Голый iperf3 между двумя серверами в одном дата-центре без конкуренции за канал почти ничего не скажет о поведении на вашем реальном маршруте с реальными соседями по полосе. Если есть возможность — тестируйте на трафике, похожем на продакшен по длительности соединений, размеру передач и степени параллелизма.
  1. Смотрите не только на среднюю скорость. Полезные метрики для сравнения — распределение RTT под нагрузкой (индикатор bufferbloat), доля повторных передач, стабильность скорости во времени, а не только пиковое значение:
ss -ti

Эта команда покажет текущий алгоритм, cwnd, RTT и статистику ретрансмиссий для активных TCP-соединений — полезно смотреть до и после переключения на одном и том же маршруте.

  1. Если сервер делит канал с чужим трафиком — проверьте именно эту конфигурацию отдельно. Тест между двумя вашими же серверами без конкурентов не покажет проблему честности разделения полосы с чужими CUBIC-потоками, если она у вас актуальна. Оценивайте поведение по возможности на реальном оверсабскрайбленном сегменте, а не только в изолированной паре.
  1. Откат должен быть таким же простым, как переключение.
sysctl -w net.ipv4.tcp_congestion_control=cubic

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

Общих ориентиров вида «BBR даёт плюс N% на длинных маршрутах» в этой статье намеренно нет — реальный прирост (или его отсутствие) сильно зависит от конкретного маршрута, характера потерь на нём и того, с кем вы делите канал, и любая усреднённая цифра из чужого блога не обязана воспроизвестись на вашей инфраструктуре.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Стоит ли включать BBR по умолчанию на всех новых серверах?

Не автоматически. Для длинных маршрутов с высоким BDP или заметными случайными потерями — вероятно, стоит протестировать в первую очередь. Для коротких соединений и стабильных внутренних каналов эффект обычно небольшой, а риск непредсказуемого поведения на общем оверсабскрайбленном канале — реальный. Тестируйте под свою нагрузку, а не включайте по умолчанию для всего парка сразу.

Как понять, что причина медленной скорости — именно алгоритм перегрузки, а не что-то другое?

Сравните поведение одного и того же маршрута с разными алгоритмами при прочих равных и смотрите на паттерн потерь, рост RTT под нагрузкой и стабильность скорости, а не только на пиковое число. Если картина заметно меняется от переключения алгоритма — дело в congestion control; если нет, скорее всего узкое место в другом — размере TCP-окна, физическом лимите канала или MTU.

Правда ли, что BBR отбирает полосу у соседних CUBIC-потоков?

Это была одна из главных тем публичной критики ранних версий BBR, и более поздние доработки алгоритма были направлены на улучшение честности сосуществования с классическими потоками. Насколько полно проблема решена именно в вашей версии ядра — стоит проверять по актуальной документации, а не считать вопрос однозначно закрытым или, наоборот, однозначно нерешённым.

Нужно ли включать fq отдельно при переходе на BBR?

Да, это рекомендуемая связка: BBR проектировался с расчётом на fair queueing как дисциплину очереди на исходящем интерфейсе, и без неё поведение алгоритма может отличаться от документированного. Команда sysctl -w net.core.default_qdisc=fq — часть корректной настройки, а не опциональный шаг.

Можно ли держать разные алгоритмы на разных серверах одного проекта?

Да, алгоритм congestion control настраивается на уровне отправителя и не требует, чтобы обе стороны соединения использовали один и тот же. Это удобно для постепенного раската: перевести часть узлов на BBR, оставить остальные на CUBIC и сравнить метрики между группами на реальном трафике, прежде чем принимать решение по всему парку.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →