Почему пинг ничего не говорит: jitter, потери пакетов и bufferbloat
Почему пинг ничего не говорит: jitter, потери пакетов и bufferbloat
Вообще я микроразработчик, со мной можно связаться как угодно, я открыт ко всему
Сторонний мой проект: Zapret2UI.
ping 12 ms. Отлично же, канал шикарный.
А потом созвон рассыпается на слоги, в игре персонаж телепортируется, страницы то грузятся мгновенно, то думают по три секунды. Идёте проверять - ping всё те же 12 мс. Идёте на спидтест - 300 Мбит. По всем приборам здорово, по факту пользоваться невозможно.
Так вот, ping не сломан. Он честно показывает ровно одну цифру, а вам нужны три другие. И самое обидное - та единственная цифра, которую он показывает, для половины реальных задач вообще не главная.
Разберём, что там на самом деле происходит: почему средний пинг скрывает всё интересное, почему ICMP - это в принципе не ваш трафик, откуда берётся jitter и как он превращается в рваный звук, почему один процент потерь роняет гигабитный канал до полутора мегабит, и что такое bufferbloat - беда, которую породили из лучших побуждений.
Кому пригодится: если выбираете хостера и смотрите только на пинг из своего города; если сервис «то работает, то нет», а метрики зелёные; или если хочется наконец понять, что показывает mtr и почему там красное на середине пути.
Половина команд ниже пересекается с чеклистом по проверке VPS - там про то, что вам дали по железу, а тут про то, что дали по сети.
Содержание
- Что на самом деле меряет ping
- ICMP это не ваш трафик
- Jitter: почему рассыпается голос
- Один процент потерь и мёртвый гигабит
- Bufferbloat: беда от лишней памяти
- Как читать mtr и не паниковать
- Чем мерить по-настоящему
- Что чинится, а что нет
- Какая метрика под какую задачу
- Частые ошибки
- Где это проверять
- Короткий итог
Что на самом деле меряет ping
Утилита отправляет ICMP Echo Request, ждёт Echo Reply, засекает время. Получается RTT - время туда и обратно. Одно число, усреднённое по десятку пакетов.
Смотрим на типичный вывод внимательнее, чем обычно:
--- 1.1.1.1 ping statistics ---
100 packets transmitted, 100 received, 0% packet loss, time 20147ms
rtt min/avg/max/mdev = 11.2/14.8/197.4/21.3 ms
Все смотрят на avg - 14,8 мс, красота. А теперь гляньте на max: 197 мс. Какой-то пакет ехал в тринадцать раз дольше средней. Средняя это проглотила и не поперхнулась, потому что среднее так и работает: девяносто девять хороших замеров прячут один плохой.
Для скачивания файла такой выброс не значит ничего. Для голосового звонка это щелчок в ухе.
mdev - самое полезное поле, и самое игнорируемое. Формально «среднее отклонение», по факту iputils считает там обычное стандартное отклонение RTT. То есть насколько замеры разбросаны вокруг средней. Вот это уже близко к тому, что называют jitter'ом, хотя строго говоря не он (настоящий jitter по RFC 3550 считается по-другому - как сглаженное среднее разниц между соседними пакетами, а не как разброс вокруг центра). Для бытовой диагностики разница несущественная: если mdev заметно больше нуля, канал дёргается.
Четыре вещи, которые ping не покажет никогда
Он не различает направления. RTT - это сумма. 100 мс могут быть двадцатью туда и восьмьюдесятью обратно, и это не редкость: маршруты в интернете асимметричны по умолчанию, обратный путь почти всегда идёт не через те же роутеры. А чинить надо тот, который тормозит. По RTT вы не поймёте какой.
Он врёт про ваш собственный Wi-Fi. Беспроводная сеть добавляет свой разброс: повторы, коллизии, смена скорости на лету, энергосбережение на ноутбуке. Меряете пинг до сервера по вайфаю и половину результата приносите из соседней комнаты. Меряйте по проводу, иначе диагностируете свой роутер, а думаете, что диагностируете хостера.
Он молчит про поведение под нагрузкой. Пустой канал отвечает за 12 мс. Начали качать - и стало 800. Обычный ping в простое этого не увидит вообще, а именно это состояние вы и ощущаете как «интернет тупит».
Десять пакетов - не статистика. Дефолтный ping на винде шлёт четыре пакета, на линуксе гоняет до Ctrl+C, но обычно люди смотрят секунд пять. А те проблемы, которые и портят жизнь, вылезают раз в минуту. Гоняйте так:
ping -c 300 -i 0.2 1.1.1.1
Триста пакетов с интервалом в 200 мс, минута работы. И смотреть надо на max и mdev, а не на avg.
ICMP это не ваш трафик
Вот это, пожалуй, главное, что стоит унести из статьи. Вы меряете один протокол, а пользуетесь другим, и сеть относится к ним по-разному.
Причина первая: роутеры ICMP не любят. Когда пакет просто проезжает через маршрутизатор, его обрабатывает специализированное железо на полной скорости порта. А когда роутеру надо самому ответить (на ping или на traceroute-зонд с истёкшим TTL) - это работа для процессора управляющей платы. Процессор там слабенький, и защищать его надо, иначе любой школьник положит железку одним скриптом. Поэтому на всех нормальных роутерах стоит ограничение: отвечаю на столько-то ICMP в секунду, остальное молча выкидываю.
В линуксе, кстати, это видно прямо в sysctl:
sysctl net.ipv4.icmp_ratelimit
# net.ipv4.icmp_ratelimit = 1000
Значение в миллисекундах: минимальный интервал между ответами определённых типов. Ваш сервер тоже так делает, просто вы об этом не думали.
Итог: потери в ping'е могут означать «роутер поленился ответить», а транзитный трафик через него в это время шёл без единой потери на полной скорости.
Причина вторая: провайдеры режут ICMP как класс. Не со зла, а потому что он не приносит денег и его удобно душить первым при перегрузке. Некоторые вообще ставят ему низший приоритет в очередях. Ваш пинг деградирует первым, хотя реальный трафик ещё в порядке. Бывает и наоборот: у хостера ICMP пролетает шикарно, а TCP-сессии рвутся.
Причина третья, самая недооценённая: вы едете не по тому проводу. Между крупными точками сети обычно не один линк, а несколько параллельных, и трафик по ним раскидывают через ECMP - хешируют пятёрку из адреса отправителя, адреса получателя, протокола и двух портов, и по хешу выбирают линк. Это нужно, чтобы пакеты одного соединения не переставлялись местами.
Только у ICMP портов нет. Вообще. Значит, и хеш у него считается по другим данным, значит, и линк ему достанется другой. Ваш ping едет по волокну номер три, а ваш HTTPS на 443-й порт - по волокну номер семь. Третье свободно, седьмое забито. Пинг прекрасен, сайт не грузится, и оба измерения честные.
Практический вывод. Хотите узнать, как себя чувствует ваш трафик - меряйте тем же протоколом, каким ходите:
# TCP-режим mtr, зонды идут SYN-пакетами на 443
mtr -T -P 443 -rwzbc 200 example.com
# то же самое через hping3
hping3 -S -p 443 -c 20 example.com
Разница между mtr и mtr -T -P 443 до одного и того же адреса иногда шокирует. Если ICMP-вариант показывает 3% потерь, а TCP-вариант ноль - никаких потерь у вас нет, вам просто не отвечали.
Это же, кстати, причина не ставить в мониторинге проверку типа Ping и на том успокаиваться - подробнее в статье про свой мониторинг.
Jitter: почему рассыпается голос
Jitter - разброс задержки. Не сама задержка, а то, насколько она скачет от пакета к пакету.
И вот тут контринтуитивная вещь, которую надо принять: стабильные 80 мс лучше, чем скачущие от 20 до 200. Даже если во втором случае бывает вдвое быстрее. Для всего реального времени - голос, видео, игры - предсказуемость важнее скорости.
Механизм: буфер джиттера
Голос по сети едет мелкими пакетами, обычно по 20 мс звука в каждом. Отправитель шлёт их идеально ровно, через равные промежутки. Сеть эту ровность разрушает: один пакет постоял в очереди, второй проскочил, третий поехал другим маршрутом.
На приёмной стороне поток надо собрать обратно в ровный, иначе звук будет ускоряться и замедляться. Для этого стоит jitter buffer: приёмник придерживает пакеты, копит запас, скажем, на 50 мс, и отдаёт их декодеру равномерно.
Дальше самое интересное. Пакет, который опоздал сильнее, чем глубина буфера, - выбрасывается. Не потому, что сеть его потеряла, - сеть его честно доставила. Просто он приехал, когда этот кусочек звука уже прозвучал, и он больше не нужен.
Получается, jitter превращается в потери на уровне приложения, даже когда в сети потерь ноль. Вы смотрите на статистику канала, там 0% packet loss, а собеседник слышит вас пунктиром.
Умные буферы подстраиваются: видят разброс - увеличивают глубину. Меньше выброшенных пакетов, но растёт задержка, и разговор превращается в переговоры по рации с паузами и «алло, ты меня слышишь?». Выбор всегда один и тот же: либо рвётся, либо тормозит.
Сколько это в цифрах
Тут есть настоящий ориентир, а не выдуманный. В рекомендации ITU-T G.114 давно расписаны пороги по односторонней задержке: до 150 мс большинство людей не замечает вообще, 150-400 мс уже чувствуется, но разговаривать можно, выше 400 мс - разговор ломается, собеседники начинают перебивать друг друга.
Обратите внимание: односторонней. То есть примерно половина того RTT, который вам показывает ping. Гоняете голос через сервер с пингом 250 мс - у вас 125 мс в одну сторону только на сеть, плюс кодирование, плюс буфер, плюс декодирование. Бюджет съеден.
Про сам разброс жёсткого стандарта нет, но по практике: mdev в пределах единиц миллисекунд - канал ровный, десятки - уже слышно, сотни - можно не звонить.
Откуда берётся
- Очереди на перегруженном участке. Основной источник. Пакет ждёт своей очереди столько, сколько занято впереди, а занятость всё время меняется.
- Wi-Fi. Само по себе. Общая среда, коллизии, повторные передачи, адаптация скорости, засыпающий радиомодуль ради экономии батареи.
- Мобильная сеть. Там задержка вообще живёт своей жизнью, особенно при переключении между сотами.
- Bufferbloat. Об этом дальше отдельно, он даёт самый зрелищный разброс.
Один процент потерь и мёртвый гигабит
«Ну потерялся один пакет из ста, невелика беда, TCP же перешлёт». Перешлёт. Только сначала он сделает вывод.
TCP в классических реализациях (Reno, CUBIC, который стоит по умолчанию в линуксе) считает потерю пакета сигналом перегрузки. Логика родом из восьмидесятых и вполне здравая: провода не теряют пакеты просто так, теряют переполненные очереди, значит сеть перегружена, значит надо сбавить. И отправитель режет окно, а потом медленно наращивает обратно.
Пока потери случайные и редкие - механизм работает. Когда потери идут постоянно, окно не успевает вырасти между просадками, и скорость встаёт колом. Причём встаёт независимо от ширины канала.
Считается это формулой Матиса. Верхняя граница для одного TCP-потока получается примерно такая: размер сегмента, делённый на RTT, умноженный на константу и делённый на корень из вероятности потери. Подставим реальные числа (сегмент 1460 байт):
| Потери | RTT 20 мс | RTT 100 мс |
|---|---|---|
| 0,01% | ~71 Мбит/с | ~14 Мбит/с |
| 0,1% | ~22 Мбит/с | ~4,5 Мбит/с |
| 1% | ~7 Мбит/с | ~1,4 Мбит/с |
Прочитайте правый нижний угол ещё раз. Один процент потерь на канале с пингом 100 мс - и одно TCP-соединение не разгонится выше полутора мегабит. Хоть у вас десятигигабитный порт, хоть сто. Ширина канала в формуле не участвует вообще.
Вот почему «у меня же гигабит, почему файл качается со скоростью модема» - вопрос не про гигабит.
Отсюда растёт куча знакомых странностей
Спидтест показывает норму, а скачивание ползёт. Спидтесты качают в несколько потоков одновременно. Каждый поток по отдельности страдает от потерь, но их десять, и в сумме получается прилично. Одиночная закачка через curl - это один поток, и он получает свои полтора мегабита. Ровно этот эффект вы видите, когда iperf3 -P 8 из чеклиста по проверке VPS даёт совсем не то, что iperf3 в один поток.
Браузер шустрее, чем консольная утилита. По той же причине: он открывает несколько соединений и тянет ресурсы параллельно.
Помогает смена congestion control. BBR не использует потери как основной сигнал перегрузки, он строит модель канала по измеренной полосе и минимальному RTT. На линии с фоновыми потерями разница бывает в разы, и именно поэтому его так любят вкручивать в прокси-конфиги. Правда, включается он не в конфиге прокси, а в ядре (net.ipv4.tcp_congestion_control), и если модуль не загружен, строчка в конфиге не значит ничего - я про это писал подробно в разборе конфигов Xray. Ещё BBR довольно нагло ведёт себя по отношению к соседним потокам, так что серебряной пулей его считать не стоит.
Не все потери одинаковы
Для скорости важен процент. Для голоса и игр важнее как они распределены.
Один процент, размазанный ровно по всему потоку, современный голосовой кодек замаскирует так, что вы не заметите: он достроит недостающий кусочек по соседним. А вот тот же один процент, прилетевший пачкой из пяти пакетов подряд, - это сто миллисекунд тишины, которую ничем не замаскируешь. Такие пачки как раз и дают роутеры, когда переполняется очередь: они выкидывают не по одному, а всё, что не влезло, разом.
Отдельная категория для российских реалий
Потери бывают не сетевыми. Если соединение стабильно рвётся на определённых сайтах, на определённом порту или строго после начала передачи данных, а до соседнего сервера в том же дата-центре всё летает - это уже не про качество канала. Отличить такое легко: настоящие сетевые потери не разбирают, куда вы идёте, и бьют одинаково по всем адресам за проблемным участком. Избирательность - признак того, что кто-то смотрит внутрь.
Bufferbloat: беда от лишней памяти
Моя любимая история в сетях, потому что она про то, как хорошее намерение всё сломало.
Память дешевела, и производители сетевого железа рассуждали логично: чем больше буфер, тем меньше пакетов придётся выбросить при всплеске нагрузки. Потери - это плохо, значит, буферы делаем побольше. И набили их в модемы, роутеры, базовые станции, драйверы сетевых карт.
Проблема в том, что TCP узнаёт о перегрузке из потерь. Это его единственный надёжный сигнал.
Смотрите, что получается. Канал забился, но пакеты не выбрасываются - они выстраиваются в очередь. Отправитель потерь не видит, делает вывод, что всё отлично, и разгоняется дальше. Очередь растёт. Отправитель разгоняется ещё. Очередь растёт ещё.
К тому моменту, когда сигнал о перегрузке всё-таки дойдёт, в буфере уже лежат секунды трафика. И каждый пакет теперь проходит через эту очередь. Ваш DNS-запрос, ваш ping, ваш пакет с голосом - все послушно встают в хвост за тремя мегабайтами торрента.
Вот классическая картина, которую видел каждый, но мало кто знал, как она называется:
в простое: ping 15 мс
началась закачка: ping 780 мс
Никаких потерь, никаких ошибок. Просто интернет превратился в кисель, пока что-то качается. Буферы, которые ставили ради борьбы с потерями, обменяли потери на задержку - причём по грабительскому курсу.
Почему это не видно обычными тестами
Спидтест меряет полосу. Полоса при bufferbloat отличная, буфер же её и обеспечивает. Ping в простое тоже отличный, очереди пустые.
Мерить надо задержку под нагрузкой - latency under load. То есть одновременно грузить канал и пинговать. Ровно это и делают специальные тесты вроде Waveform или LibreQoS: сначала замер в покое, потом заливка вниз с параллельным замером, потом заливка вверх, и на выходе оценка буквой от A+ до F. Первый раз это стоит прогнать просто из любопытства, результат обычно бодрит.
Руками то же самое делается в два окна:
# окно 1
ping -i 0.2 1.1.1.1
# окно 2 - грузим канал на 30 секунд
iperf3 -c <сервер> -t 30 -P 4
Смотрите, что происходит с пингом в первом окне в момент старта заливки. Вырос в десять раз - у вас bufferbloat.
Лечение: AQM
Идея активного управления очередью в том, чтобы начинать отбрасывать пакеты до того, как очередь распухнет. Не когда буфер полон, а когда пакеты начали в нём залёживаться.
CoDel (RFC 8289) зашёл с неожиданной стороны: он следит не за длиной очереди, а за временем, которое пакет в ней проводит. Логика в том, что длина очереди сама по себе ни о чём не говорит - короткий всплеск - это нормально, плохо, когда очередь не рассасывается. Как только время ожидания стабильно превышает целевое (по умолчанию 5 мс), CoDel начинает подкидывать дропы, и отправитель получает свой сигнал притормозить.
FQ-CoDel (RFC 8290) добавил сверху справедливое разделение по потокам. Каждый поток получает свою очередь, и торрент в сорок соединений физически не может отодвинуть ваш единственный пакет с голосом в конец. Это и есть та штука, из-за которой на нормально настроенном роутере зум не замечает, что рядом качается образ убунты.
CAKE - развитие идеи, всё в одном флаконе: шейпер, честное разделение, приоритизация, учёт накладных расходов канала. В ядре Linux с версии 4.19.
На сервере проверяется одной командой:
sysctl net.core.default_qdisc
tc qdisc show dev eth0
Хорошая новость: на современных дистрибутивах с systemd там, скорее всего, уже стоит fq_codel - systemd прописывает его в своих дефолтных sysctl'ах ещё с 2014 года, специально ради борьбы с bufferbloat. Так что если увидите древний pfifo_fast - либо система очень старая, либо кто-то это переопределил руками.
Меняется так:
# разово
tc qdisc replace dev eth0 root fq_codel
# насовсем
echo 'net.core.default_qdisc = fq_codel' | sudo tee /etc/sysctl.d/99-aqm.conf
sudo sysctl --system
Честная оговорка про то, где это работает
Очередь на вашем сервере управляет только исходящим трафиком с этого сервера. Если бутылочное горлышко находится у провайдера или на магистрали - вы этой очередью не управляете и сделать с ней ничего не можете. Никакой qdisc на VPS не починит перегруженный пиринг.
На домашнем роутере смысла больше, но там есть свой фокус: чтобы AQM работал, очередь должна образоваться у вас, а не у провайдера. Поэтому в настройках SQM скорость шейпера ставят на 85-95% от реальной - вы намеренно немного жертвуете полосой, зато узкое место переезжает на ваше устройство, где вы им распоряжаетесь. Отдать несколько процентов скорости в обмен на то, что задержка под нагрузкой не улетает в небо, - обмен более чем выгодный.
Куда всё это движется
Современное продолжение темы - L4S (RFC 9330). Идея в том, чтобы вообще перестать использовать потери как сигнал: сеть помечает пакеты специальным флагом ECN задолго до того, как очередь станет проблемой, а отправитель на это реагирует. Плюс две отдельные очереди, чтобы новый механизм не конфликтовал со старым. Дело уже не чисто теоретическое: оператор T-Mobile в США раскатал L4S по своей 5G-сети. До массовых домашних провайдеров дойдёт нескоро, но направление задано.
Как читать mtr и не паниковать
mtr - это traceroute и ping в одном флаконе: гоняет зонды непрерывно и показывает статистику по каждому хопу. Инструмент отличный, но читают его неправильно примерно все, и в поддержку хостеров ежедневно летят скриншоты с паникой на пустом месте.
Типичный вывод:
HOST Loss% Snt Last Avg Best Wrst StDev
1. 192.168.1.1 0.0% 200 0.4 0.5 0.3 1.2 0.1
2. 10.20.0.1 0.0% 200 2.1 2.4 1.9 8.7 0.6
3. core1.isp.net 14.5% 200 3.8 4.1 3.2 12.4 0.9
4. border.isp.net 0.0% 200 5.2 5.5 4.8 15.1 1.1
5. ix-peering.net 0.0% 200 18.3 18.9 17.9 28.2 1.3
6. target.example.com 0.0% 200 19.1 19.6 18.8 31.5 1.5
Третий хоп горит красным - 14,5% потерь. Вроде найден виновник, можно писать гневное письмо.
Не надо. Смотрите на строчку ниже: там ноль.
Разгадка в том, о чём мы говорили выше. Чтобы показаться в трассировке, роутер должен сам сгенерировать ICMP-ответ - а это работа для его управляющего процессора, и он её ограничивает. Транзитный трафик при этом идёт через ту же железку в полном порядке, потому что его обрабатывает совсем другой тракт. Роутер не потерял ваши пакеты, он поленился ответить на зонды.
Правило чтения ровно одно: потери реальны, только если они начинаются на каком-то хопе и держатся до самого конца. Пропали на следующей строке - забудьте, это ограничение ICMP, а не проблема сети.
И наоборот, вот такая картина - настоящая беда:
3. core1.isp.net 6.2% 200 3.8 4.1 3.2 12.4 0.9
4. border.isp.net 6.5% 200 5.2 5.5 4.8 15.1 1.1
5. ix-peering.net 6.1% 200 18.3 18.9 17.9 28.2 1.3
6. target.example.com 6.4% 200 19.1 19.6 18.8 31.5 1.5
Потери появились на третьем хопе и дошли до конца примерно теми же процентами. Вот теперь виноват третий, и вот с этим уже можно идти в поддержку.
Последняя строка вообще самая главная. Если на ней ноль - у вас всё хорошо, что бы ни творилось выше.
Второй момент, про который забывают: трасса односторонняя
mtr видит только путь от вас к цели. Обратный путь может идти вообще через другие страны, и если проблема там - в вашей трассировке она не отобразится никак. Вы будете смотреть на идеальный вывод и не понимать, почему всё плохо.
Поэтому правило обращения в поддержку: прикладывать два отчёта - свой до сервера и встречный, снятый на сервере до вашего адреса. Одностороннюю трассу поддержка первым делом попросит дополнить, так что сэкономьте себе круг переписки.
# у себя
mtr -rwzbc 200 <IP-сервера> > mtr-to-server.txt
# на сервере (ваш публичный адрес узнаётся через curl ifconfig.me)
mtr -rwzbc 200 <ваш-IP> > mtr-from-server.txt
Флаги: -r отчёт вместо интерактива, -w широкий вывод с полными именами, -z показывать номера автономных систем (сразу видно, где кончается один оператор и начинается другой), -b показывать и имя, и адрес, -c 200 сколько зондов гонять.
Чем мерить по-настоящему
Собрал в кучу то, чем реально пользуюсь.
Разброс задержки, без затей:
ping -c 300 -i 0.2 <цель>
Триста пакетов, минута. Смотрим mdev и max, на avg не ведёмся.
Тем протоколом, которым ходим:
mtr -T -P 443 -rwzbc 200 <цель>
Если ICMP-версия показывает потери, а эта нет - потерь нет.
Честный jitter и потери разом. UDP-режим iperf3 для этого и сделан: он шлёт с заданной скоростью и на приёмнике считает и разброс, и сколько датаграмм не доехало.
iperf3 -c <сервер> -u -b 50M -t 30
В отчёте будут колонки Jitter и Lost/Total. Это самый прямой ответ на вопрос «что там с каналом», какой можно получить за тридцать секунд.
Односторонняя задержка. Самая простая утилита для этого - irtt. Нужен свой сервер на другой стороне, зато вы наконец увидите, какое направление тормозит:
# на сервере
irtt server
# у себя
irtt client -i 20ms -d 30s <сервер>
Bufferbloat. Браузерные тесты latency under load (Waveform, LibreQoS) дают оценку буквой за две минуты. Руками - ping в одном окне и iperf3 в другом, как выше.
Быстрая общая картина. speed.cloudflare.com кроме скорости показывает задержку под нагрузкой, разброс и потери. Для «глянуть одним глазом» удобнее всего.
Что за очередь стоит:
tc qdisc show dev eth0
Из-под винды: pathping (встроенный, совмещает трассировку со статистикой потерь, только долго думает) и psping из Sysinternals - он умеет TCP-режим, то есть обходит проблему деприоритезации ICMP.
Два правила замера, без которых всё бессмысленно
Мерьте по проводу. Wi-Fi добавляет свой разброс, и вы не отличите его от сетевого. Хотите проверить хостера - воткните кабель.
Мерьте в разное время суток. Перегруженный пиринг живёт по расписанию: днём всё летает, вечером всё встаёт. Один замер в три часа дня не значит ничего - ровно та же история, что и с оверселлом железа.
Что чинится, а что нет
Честное разделение, потому что половину проблем с сетью чинить бесполезно, и лучше знать об этом заранее.
Чинится вами:
- Домашний роутер и его буферы. SQM с fq_codel или CAKE, шейпер на 90% реальной скорости. Часто это вообще единственная реальная проблема, а грешат на провайдера.
- Wi-Fi. Провод, смена канала, разнос точек. Скучно, но работает.
- Очередь на исходящем интерфейсе вашего VPS -
fq_codel, одна строчка в sysctl. - Алгоритм контроля перегрузки на вашем сервере. BBR вместо CUBIC там, где линия с фоновыми потерями.
- MTU и фрагментация. Отдельная классика: где-то по пути MTU меньше вашего, а ICMP с сообщением об этом отфильтрован, и в результате мелкие пакеты ходят, а крупные исчезают. Выглядит как мистика («ping идёт, сайт не грузится»), лечится подбором MTU.
Не чинится вами никак:
- Перегруженный стык между вашим провайдером и хостером. Хоть обнастраивайтесь.
- Потери в магистрали.
- Кривая оптика на промежуточном участке.
- Асимметричный маршрут, где обратный путь идёт через полмира.
Единственное лекарство от второй группы - сменить маршрут. То есть другая локация дата-центра, другой хостер, другой аплинк. Иногда переезд сервера из одного города в другой у того же провайдера чинит всё, потому что трафик поехал через другой стык.
Именно поэтому при выборе хостера пинг из вашего города - метрика более полезная, чем характеристики железа. Железо у всех примерно одинаковое, а вот маршруты до вашего провайдера у всех разные.
Какая метрика под какую задачу
| Задача | Что реально критично | Что почти не важно |
|---|---|---|
| Веб-сёрфинг | RTT: каждое новое соединение начинается с рукопожатий, и они складываются | jitter, полоса сверх десятков мегабит |
| Видеозвонки | jitter и потери, они бьют напрямую по звуку | абсолютная скорость |
| Игры | jitter и потери пачками, стабильность важнее среднего | полоса, там копейки трафика |
| Скачивание большого файла | потери (см. таблицу выше) и полоса | jitter |
| Просмотр видео | стабильность полосы, буфер плеера сглаживает остальное | RTT, jitter |
| Прокси и VPN | потери плюс эффект TCP внутри TCP | средний RTT сам по себе |
Отдельно про последнюю строку. Когда TCP-соединение едет внутри другого TCP-соединения, оба слоя начинают независимо реагировать на одни и те же потери и мешают друг другу: внешний уже перепослал, а внутренний тоже решил перепослать. Получается затор от одной-единственной пробки. Разбирал это подробно в сравнении протоколов, тут просто отмечу, что на рваном канале эффект вылезает первым делом, и именно поэтому протоколы поверх UDP на плохих линиях чувствуют себя заметно лучше.
Частые ошибки
- Смотреть на
avgи радоваться. Средняя прячет ровно те выбросы, которые вы и ощущаете. Смотритеmaxиmdev. - Судить о канале по десяти пакетам. Проблема, которая всплывает раз в минуту, в пятисекундном замере не появится.
- Паниковать от красного посередине
mtr. Если на последнем хопе ноль - потерь нет, вам просто не отвечал промежуточный роутер. - Мерить по Wi-Fi. Вы диагностируете свою квартиру, а не хостера.
- Считать, что ping и рабочий трафик едут одинаково. Разный приоритет, разное отношение оборудования, при ECMP - буквально разные провода.
- Игнорировать нагрузку. Bufferbloat в простое не виден в принципе. Тест без нагрузки его не поймает никогда.
- Присылать в поддержку одну трассу. Обратный путь другой, без встречного отчёта половина картины отсутствует.
- Гнаться за минимальным пингом любой ценой. Стабильные 60 мс лучше, чем 25 с выбросами до 300. Для всего живого предсказуемость дороже.
- Верить одному замеру. Вечерний час пик - отдельная реальность, и именно в ней вы обычно и пользуетесь интернетом.
Где это проверять
Всё, что выше, требует второй точки. Пинг сам с собой не померишь: чтобы понять, дело в канале или в сервисе, нужна машина на другом конце, про которую вы точно знаете, что с ней всё в порядке.
Дешёвый VPS в этой роли незаменим. На нём поднимается iperf3 -s, ставится irtt server, с него снимается встречный mtr - и внезапно все замеры становятся двусторонними и осмысленными. Плюс появляется возможность проверить главное перед покупкой чего-то серьёзного: как из вашей сети доезжает до этого конкретного дата-центра, потому что цифры в оффере про это не говорят ничего.
Я для такого держу самый младший тариф на serv.host (промокод promo22382) - под iperf3 и трассировки хватает минимальной конфигурации, а разные локации позволяют сравнить маршруты и выбрать тот, который до вас доезжает нормально.
Порядок первой диагностики нового сервера, если нужен готовый список:
ping -c 300 -i 0.2до сервера, смотримmaxиmdev, неavg.mtr -rwzbc 200в обе стороны, читаем последнюю строку.mtr -T -P 443туда же, сравниваем с ICMP-версией.iperf3 -u -b 50M -t 30- получаем честные jitter и потери.iperf3 -c ... -t 30в один поток и-P 8- разница покажет, есть ли фоновые потери.- Пинг под нагрузкой в двух окнах - ловим bufferbloat.
- Повторить вечером. Обязательно.
Седьмой пункт снова главный, как и в проверке железа. Сеть - штука суточная.
Короткий итог
pingпоказывает одно усреднённое число туда-обратно. Ни направления, ни разброса, ни поведения под нагрузкой в нём нет.- ICMP - не ваш трафик. Роутеры ограничивают ответы на своём управляющем процессоре, провайдеры его душат, а при ECMP он вообще едет по другому физическому линку. Меряйте TCP-зондами на тот порт, которым пользуетесь.
- Jitter превращается в потери на уровне приложения: пакет, опоздавший сильнее глубины буфера, выбрасывает сам приёмник, хотя сеть его честно доставила. Стабильные 80 мс лучше скачущих 20-200.
- Один процент потерь при RTT 100 мс держит одно TCP-соединение на полутора мегабитах независимо от ширины канала. Отсюда «спидтест норм, а файл ползёт».
- Bufferbloat - это когда большие буферы прячут от TCP сигнал перегрузки, и он разгоняется, пока задержка не улетает в сотни миллисекунд. В простое не виден вообще, ловится только замером под нагрузкой.
- Лечится AQM: CoDel следит за временем в очереди, FQ-CoDel добавляет честное разделение потоков, CAKE делает всё сразу. На линуксе
fq_codelобычно уже стоит по умолчанию. - В
mtrреальны только те потери, что дошли до последней строки. Красное посередине - почти всегда ограничение ICMP на промежуточном роутере. - Половина проблем чинится на вашей стороне (роутер, Wi-Fi, qdisc, congestion control), вторая половина не чинится вообще и лечится только сменой маршрута, то есть переездом.
Хороший канал определяется не маленьким пингом, а тем, что этот пинг предсказуем и не разваливается, когда по каналу что-то поехало. Померить это ровно на пять минут дольше, чем набрать ping.
Вообще я микроразработчик, со мной можно связаться как угодно, я открыт ко всему
Сторонний мой проект: Zapret2UI.
Источники
- Bufferbloat.net - тесты и матчасть по проблеме
- RFC 8289 - Controlled Delay Active Queue Management (CoDel)
- RFC 8290 - FlowQueue-CoDel (FQ-CoDel)
- RFC 9330 - архитектура L4S
- RFC 3550 - RTP, определение interarrival jitter
- RFC 5481 - Packet Delay Variation, разбор двух определений джиттера
- tc-cake(8) - man-страница CAKE
- Как правильно читать traceroute и MTR - блог APNIC
- irtt - замер односторонней задержки
- iperf3 - официальный сайт

