Сразу скажу: ни один YouTube-гайд не заменит замеры на боевой ноде. Я долго откладывал перевод одного из узлов с CUBIC на BBR — слышал и про jitter, и про несовместимость с CAKE, и про «BBR убивает соседей по очереди». В итоге выделил выходные, поднял два идентичных VPS (Hetzner CX42, 8 vCPU, 16 GB, Ubuntu 24.04, kernel 6.8) и прогнал тесты.
Стартовая конфигурация
Все банальности — fq qdisc обязательный для BBR, иначе он просто работает как CUBIC, только хуже.
sysctl -w net.core.default_qdisc=fq
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.ipv4.tcp_notsent_lowat=131072
sysctl -w net.core.rmem_max=33554432
sysctl -w net.core.wmem_max=33554432
sysctl -w net.ipv4.tcp_rmem="4096 87380 33554432"
sysctl -w net.ipv4.tcp_wmem="4096 65536 33554432"
tcp_notsent_lowat я выставляю практически везде — снижает буферный bloat на стороне отправителя, особенно заметно на длинных сессиях с медленными клиентами. Без него BBR любит держать в очереди по 4-8 МБ.
Для BBRv3 пришлось собирать ядро 6.12 с патчем от Google — в mainline его так и не влили на момент написания. Сборка занимает около 40 минут, ничего экзотического.
Методика
Тестировал по трём сценариям:
- iperf3 (
-P 8 -t 60) между Франкфуртом и Сингапуром — RTT ~160 мс, потерь обычно <0.5% - nginx с TLS, статика 4 МБ, 200 клиентов через wrk
- реальный прод-трафик с zabbix-агента в течение суток (это самое грязное и самое полезное)
Сетевая карта виртуальная, virtio-net, никакого XDP — обычная история на VPS.
Что показал iperf
CUBIC выдал стабильные 312 Mbps на одну сессию, в 8 потоков — 1.42 Gbps. BBRv1 на одной сессии — 487 Mbps, в 8 потоков — 1.71 Gbps. BBRv3 — 521 Mbps и 1.78 Gbps. Разница между v1 и v3 не катастрофическая, но v3 заметно лучше ведёт себя при росте потерь.
Я специально дропал пакеты через tc qdisc add dev eth0 root netem loss 1.5% и смотрел деградацию:
tc qdisc add dev eth0 root netem loss 1.5% delay 80ms
iperf3 -c remote -P 4 -t 30
tc qdisc del dev eth0 root
CUBIC при 1.5% потерь упал до 41 Mbps. BBRv1 держал 220 Mbps. BBRv3 — 280 Mbps. Тут и кроется основная боль CUBIC: он считает любую потерю за сигнал перегрузки и душит окно, а в реальной сети между континентами 1-2% потерь — норма.
Nginx и wrk
Тут картина менее радужная. На коротких HTTP-ответах разницы между CUBIC и BBR практически нет — соединение слишком короткое, чтобы BBR успел набрать темп. На 4 МБ статике BBR выигрывает 15-18% по latency p99, но не больше.
wrk -t 12 -c 200 -d 60s --latency https://node-fra.example/static/test.bin
p50 у обоих около 380 мс, p99 у CUBIC — 1.8 с, у BBR — 1.45 с. Заметно, но не «вау».
Грабли, на которые наступил
Первое — tcp_congestion_control без default_qdisc=fq молча применяется, но BBR работает в режиме «как CUBIC, только странно». Проверять надо так:
ss -tin | grep -E 'bbr|cubic' | head
Если видишь cwnd в районе сотен и pacing_rate пустой — fq не активен.
Второе — BBR агрессивно ведёт себя с CUBIC-соседями. Если у вас на хосте 5 контейнеров и один с BBR — он сожрёт пропускную способность соседей. Лечится либо переводом всех на BBR, либо ограничением через tc на интерфейсе контейнера.
Третье — BBRv1 заметно хуже работает на Wi-Fi клиентах из-за специфики bufferbloat в радио. BBRv3 эту проблему частично решает.
Прод-наблюдения
После переключения боевой ноды на BBRv3 жалоб от пользователей на «медленно качается» стало кратно меньше. Средний throughput по графикам vmagent вырос с 380 до 510 Mbps на пик. Latency для дальних клиентов из Азии улучшилась процентов на 25-30.
Из неожиданного: процессор подрос на 4-6% от пейсинга. На младших VPS с 1 vCPU это может быть существенно, на 8 ядрах — не заметно вообще.
Итог
BBRv3 имеет смысл везде, где сессии длинные, а сеть неидеальна — то есть на 90% боевых нагрузок. На локальном трафике и коротких запросах прирост близок к нулю, и можно не дёргаться. Если боитесь — переключайте по одной ноде и смотрите графики неделю. CUBIC оставляйте только там, где железо реально слабое или вы знаете, что соседи зависят от честной очереди.