Тестирование глобальной CDN вашего сайта с помощью командной строки
Ваш сайт загружается за 300 миллисекунд в вашей локальной системе. Вы развертываете сеть доставки контента (CDN) — систему серверов, расположенных в разных местах, которые хранят копии вашего контента ближе к пользователям. Все выглядит быстро. Вы считаете, что дело сделано.
Но пользователь на другом континенте жалуется на медленную загрузку. На вашей панели мониторинга нет никаких проблем. Это сбивает с толку, но у этого явления есть простое объяснение. Тест с одного компьютера показывает, как ваш сайт работает только в одном месте. Он не может сказать вам, как работает ваш сайт в других регионах.
В этой статье показано, как проверить производительность CDN из командной строки в Linux. Вы узнаете, как измерить скорость соединения, проверить, обслуживает ли CDN кэшированный контент, и протестировать производительность в разных регионах. Все инструменты работают в стандартной системе Linux.
К концу теста вы сможете ответить на эти вопросы:
- Как быстро DNS находит ваш домен?
- Сколько времени требуется для установления соединения?
- Сколько времени занимает TLS-квитирование?
- Как быстро приходит первый байт контента?
- Действительно ли CDN обслуживает запрос из кэша?
- Зависит ли производительность от региона?
Почему для этого хорошо подходит командная строка
Инструменты на основе браузера показывают общее время загрузки. Они смешивают воедино сетевые задержки, время выполнения JavaScript и время рендеринга. Из-за этого сложно определить, на что именно тратится время.
Эта проблема решается с помощью инструмента командной строки curl . Он измеряет каждый этап запроса отдельно. Кроме того, он полностью пропускает рендеринг в браузере, поэтому показатели отражают только работу сети и ответ сервера.
Вот базовая команда для измерения времени выполнения одного запроса:
curl -sS -o /dev/null -w \
'DNS: %{time_namelookup}s
Connect: %{time_connect}s
TLS: %{time_appconnect}s
TTFB: %{time_starttransfer}s
Total: %{time_total}s
IP: %{remote_ip}
' \
https://example.com/
Эта команда использует curl для измерения и отображения подробных временных показателей HTTPS-соединения с example.com, без загрузки фактического содержимого веб-страницы.
Ожидаемый результат:
DNS: 0.049033s Connect: 0.078883s TLS: 0.114448s TTFB: 0.150471s Total: 0.150763s IP: 104.20.23.154

Измерение и отображение подробных метрик времени для HTTPS-соединения с доменом example.com
Эта команда игнорирует тело ответа (-o /dev/null) и выводит только данные о времени. Запустите ее для своего сайта, чтобы получить первые реальные данные.
Разбивка по частям:
| Параметр | Что он делает |
|---|---|
-sS | Беззвучный режим, но с отображением ошибок в случае их возникновения |
-o /dev/null | Игнорирует загруженное тело ответа (нам нужны только данные о времени) |
-w | Записывает пользовательский вывод после завершения передачи с использованием указанной строки формата |
Отображаемые показатели:
- DNS (
time_namelookup) — время преобразования доменного имени в IP - Подключиться (
time_connect) — время для установления TCP-соединения - TLS (
time_appconnect) — время для подтверждения связи TLS / SSL - TTFB (
time_starttransfer) — Время до первого байта (начинает поступать ответ сервера) - Всего (
time_total) — полное время запроса/ответа. - IP (
remote_ip) — IP-адрес, используемый подключением
Это полезно для:
- Мониторинга производительности — проверки скорости реакции сервера.
- Отладка — определение того, какая часть соединения является медленной (DNS, сеть, TLS или серверная обработка).
- Проверка работоспособности — проверка доступности и отзывчивости сервера без загрузки большого объема контента
Преобразование одного запроса в профиль производительности
Единственное число, например «1,2 секунды», мало о чем говорит. Запрос на самом деле выполняется поэтапно. Каждый этап можно измерить отдельно.
Вот последовательность действий:
DNS lookup
↓
TCP connection
↓
TLS handshake
↓
Request sent
↓
First byte received
↓
Transfer completed
Каждая curl временная переменная соответствует одному из следующих этапов:
time_namelookup: время преобразования доменного имени в IP-адресtime_connect: время открытия TCP-соединения с этим IP-адресомtime_appconnect: время завершения TLS-квитирования — процесса установления зашифрованного соединенияtime_starttransfer: время до получения первого байта ответа, также известное как время до первого байта (TTFB)time_total: время выполнения всего запроса
Такое разбиение позволяет найти реальный источник низкой скорости, а не гадать:
- Большое время DNS указывает на проблему с DNS.
- Большое время подключения указывает на проблему с сетью или маршрутизацией.
- Большое время до первого байта при нормальном времени подключения указывает на медленный сервер или ответ CDN.
- Большой разрыв между временем до первого байта и общим временем указывает на большой ответ или медленную передачу.
Действительно ли CDN обрабатывает запрос?
Быстрый ответ не всегда означает, что CDN справляется со своей задачей. Возможно, CDN перенаправляет каждый запрос на ваш исходный сервер, а не обслуживает его из своего кэша. Это можно проверить по заголовкам ответа.
Выполните эту команду, чтобы увидеть заголовки без загрузки тела ответа:
curl -s -o /dev/null -D - https://example.com/ | grep -iE '(cache|age|served-by)'
Пример вывода:
age: 6687 cf-cache-status: HIT
Эта команда отправляет обычный GET-запрос и игнорирует тело ответа, выводя только заголовки. Не используйте curl -I для этой проверки. Этот флаг отправляет запрос HEAD вместо запроса GET, а некоторые сети доставки контента обрабатывают запросы HEAD иначе, чем запросы GET, поскольку реальные пользователи почти всегда отправляют запросы GET. Тестирование с помощью HEAD может показать состояние кэша, которое не соответствует тому, что видят пользователи.
Ищите заголовок со статусом кэша. Название заголовка зависит от вашего CDN:
- Cloudflare использует
CF-Cache-Status, со значениямиHIT,MISS,EXPIRED,REVALIDATED,BYPASS, илиDYNAMIC. - Fastly использует
X*-Cache, со значениямиHITилиMISS, а такжеX*-Cache-Hitsдля отображения количества раз, когда этот объект был получен из кэша. Fastly также устанавливаетX*-Served-Byдля указания конкретного узла кэша, хотя сам по себе этот заголовок не указывает на попадание или промах. - Amazon CloudFront использует
X*-Cache, отформатированный какHit from cloudfrontилиMiss from cloudfront. - Akamai и устаревшая сеть доставки контента Azure используют значения
X*-Cache, такие какTCP_HITиTCP_MISS, но предоставляют эту диагностическую информацию по-разному. Azure CDN (классическая версия) обычно возвращалX*-Cacheв обычных ответах.X*-Cacheот Akamai — это в первую очередь диагностический заголовок, который обычно запрашивается явно, исторически — с помощью заголовка Pragma, напримерPragma: akamai-x*-cache-on(при необходимости в сочетании сakamai-x*-get-cache-key). Таким образом, отсутствиеX*-Cacheв обычном ответе от Akamai не следует интерпретировать как отсутствие в кэше. Теперь Akamai рекомендует для этой цели свой механизм расширенной отладки с аутентификацией.
Заголовок Age при наличии показывает, сколько секунд контент хранился в кэше.
Быстрый ответ со статусом MISS означает, что CDN обработала запрос. Быстрый ответ со статусом HIT означает, что CDN действительно выполняет свою работу. Это два разных показателя, и только один из них доказывает, что CDN работает должным образом.
Одно предостережение при таком тестировании:
curl не отправляет те же заголовки, которые браузер отправляет по умолчанию, например Accept-Encoding для сжатия.
Некоторые сети доставки контента, в том числе CloudFront, включают нормализованную версию Accept-Encoding в ключ кэша, если включено сжатие. Без этого заголовка curl рассматривается как запрос несжатого контента, который хранится в виде отдельной кэшированной копии, отличной от сжатой версии, которую получают браузеры. Это может привести к промаху при первом запросе curl даже в том случае, если браузеры постоянно получают ответ, поскольку ваш запрос и запрос браузера соответствуют разным кэшированным копиям.
Если ваш curl тест показывает ошибку, но реальные пользователи видят быструю загрузку, стоит проверить это несоответствие, прежде чем делать вывод о реальной проблеме с кэшированием.
Примечание по Azure: Microsoft прекращает поддержку Azure CDN Standard от Microsoft (классическая версия) в пользу Azure Front Door. С 15 августа 2025 года Azure CDN от Microsoft (классическая версия) больше не поддерживает создание новых профилей и подключение доменов, а полный отказ от нее запланирован на 30 сентября 2027 года. Существующие развертывания могут продолжать работать до полного отказа от сервиса, поэтому
X*-Cacheописанное выше поведение остается актуальным при тестировании классической конечной точки CDN. Для новых развертываний используйте Azure Front Door Standard или Premium. Front Door также предоставляет доступ кX*-Cache, включая такие значения, какTCP_HIT,TCP_REMOTE_HIT, иTCP_MISS, но имеет дополнительные/актуальные диагностические заголовки и соглашения.
Одного измерения недостаточно
Один запрос может ввести в заблуждение. Первый запрос к URL может привести к тому, что кэш будет пустым, а последующие запросы — к тому, что кэш будет «теплым». Состояние сети также меняется с течением времени.
Выполните один и тот же запрос несколько раз в цикле:
for i in {1..10}; do
curl -sS -o /dev/null -w \
'%{http_code} %{time_starttransfer}s %{time_total}s\n' \
https://example.com/
done
Пример вывода:
200 0,146150с 0,146868с 200 0,231786с 0,232220с 200 0,077217 с 0,077753 с 200 0,240986 с 0,241477с 200 0,682164с 0,682240с 200 0,132748с 0,133461с 200 0,410818 с 0,933873с 200 0,087598 с 0,088383с 200 0,256964 с 0,745285с 200 0,679765с 0,882171с
Обращайте внимание на закономерность в десяти результатах, а не только на одну строку. Холодный кэш часто показывает более медленный первый запрос, за которым следуют более быстрые.
Стабильные показатели говорят о стабильном кэше. Резкие колебания указывают на проблему, которую стоит изучить подробнее. Медианное значение обычно более показательно, чем среднее, поскольку один медленный запрос может исказить среднее значение, не отражая типичную производительность.
Понимание того, что на самом деле делает кэш CDN
Основная задача CDN — кэширование, а не просто физическая близость к пользователю. Если вы разберетесь в нескольких терминах, вам будет проще понять остальную часть этого руководства.
- Попадание в кэш: CDN нашла действительную сохраненную копию контента и выдала ее напрямую.
- Промах в кэше: CDN не нашла действительную копию и ей пришлось запрашивать ее с исходного сервера.
- TTL (время жизни): время, в течение которого CDN хранит кэшированную копию, прежде чем считать ее просроченной.
- Ключ кэша: набор значений, которые CDN использует для определения того, должны ли два запроса возвращать один и тот же кэшированный контент.
- Исходный запрос: запрос, который CDN отправляет на ваш реальный сервер, только в случае промаха в кэше.
- Edge location: сервер CDN, расположенный близко к пользователям, где хранится и обслуживается кэшированный контент.
Ключ кэша имеет большее значение, чем кажется на первый взгляд. Если ваша сеть доставки контента содержит в ключе кэша ненужные элементы, такие как дополнительные заголовки запросов, файлы cookie или параметры строки запроса, это приводит к созданию большего количества вариантов кэша.
Чем больше вариантов, тем больше промахов в кэше, поскольку меньше запросов соответствуют существующей кэшированной копии. Чем проще ключ кэша, тем выше коэффициент попаданий — процент запросов, которые обслуживаются из кэша, а не из источника.
Обходной путь для Linux: IPv4 или IPv6
Большинство современных систем поддерживают как IPv4, так и IPv6. Производительность может различаться в зависимости от вашего сетевого маршрута и маршрутизации CDN.
Протестируйте каждую версию отдельно:
curl -4 -sS -o /dev/null -w '%{time_total}\n' https://example.com/curl -6 -sS -o /dev/null -w '%{time_total}\n' https://example.com/
Если один из них заметно медленнее, разница может указывать на проблему с маршрутизацией, характерную для одного из протоколов. Это стоит проверить, поскольку некоторые сети обрабатывают IPv6 менее эффективно, чем IPv4, и наоборот.
Проверка производительности HTTP/3
Большинство крупных сетей доставки контента теперь поддерживают HTTP/3 — версию протокола, которая работает через QUIC, а не через TCP. QUIC — это транспортный протокол, основанный на UDP. Это устраняет проблему, известную как блокировка в начале очереди, когда один потерянный пакет приводит к задержке всех потоков в соединении. Благодаря этому HTTP/3 может работать заметно быстрее в сетях с потерей пакетов, например в мобильных сетях.
Для тестирования этой функции в вашей curl сборке должна быть поддержка QUIC, которая не включена в большинство пакетов Linux по умолчанию. Проверьте, поддерживает ли ее ваша сборка:
curl --version | grep -i http3
Если поддержка HTTP / 3 отсутствует, вы все равно можете подтвердить, что сервер предлагает ее, проверив Alt-Svc заголовок ответа:
curl -s -o / dev / null -D - https://example.com / | grep -i alt-svc
Если ваша curl сборка поддерживает HTTP / 3, сравните ее непосредственно с HTTP / 2:
FORMAT='Протокол: %{http_version} Итого: %{time_total}s\n'
curl -s -o /dev/null --http2 -w "$FORMAT" https://example.com /
curl -s -o /dev/null --http3 -w "ФОРМАТ $" https://example.com/
Проверьте значение %{http_version} в выводе, чтобы узнать, какой протокол был использован на самом деле.
При запросе --http3 curl сначала пытается установить QUIC-соединение, а затем автоматически переключается на HTTP/2, если QUIC не работает или работает слишком медленно. Этот запасной вариант выполняется незаметно, поэтому запрос выполняется успешно, даже если HTTP/3 не работает. Поле version в выводе — единственный надежный способ узнать, какой протокол был использован.
DNS — это часть пути, а не просто поиск
Разрешение DNS не является отдельным этапом, влияющим на производительность CDN. Это часть пути. Многие сети доставки контента используют DNS для перенаправления пользователей к ближайшему периферийному серверу, поэтому IP-адрес, который вы получите в ответ на DNS-запрос, может меняться в зависимости от вашего местоположения.
Проверить текущее разрешение можно с помощью dig:
dig example.com
Для более короткого вывода, отображающего только разрешенный IP-адрес:
dig +short example.com
Различайте три вещи: этап разрешения DNS, возвращаемый IP-адрес и фактическое местоположение CDN, которое в итоге обрабатывает ваш HTTP-запрос.
Команда dig показывает первые два параметра. Она не подтверждает, какое физическое устройство обработало ваш запрос. Для этого лучше использовать заголовки ответа, о которых мы говорили ранее.
Реализация: одна машина, одна точка обзора
Все тесты до сих пор проводились на одном оборудовании в одном месте. Это основное ограничение всего, что было рассмотрено до этого момента. Ваши измерения точны, но они описывают производительность только с того места, где вы находитесь.
Это важно, потому что CDN перенаправляют пользователей в разные пограничные местоположения в зависимости от того, откуда исходит запрос. Хорошо работающий для вас CDN может перенаправить пользователя из другого региона в более медленное или неправильно настроенное пограничное местоположение, и вы никогда не увидите его со своего компьютера.
Следующий шаг — провести те же тесты в нескольких регионах и сравнить результаты. Вам не нужно искать самый быстрый показатель. Вам нужно выявить закономерности:
- Один регион стабильно работает медленнее других?
- Сильно ли различается время до первого байта в разных регионах?
- В разных регионах разный статус кэша для одного и того же контента?
- Некоторые регионы подключаются к другому пограничному серверу, чем ожидалось?
- Отличается ли производительность IPv4 или IPv6 в разных регионах?
Получение запросов из нескольких регионов
Чтобы протестировать работу из нескольких регионов, вам нужны запросы, которые действительно поступают из этих регионов. Есть несколько практических способов это сделать.
Первый вариант — это инфраструктура, которую вы уже контролируете в других регионах, например существующие серверы или филиалы. Это дает вам полный контроль над тестовой средой, но работает только в том случае, если у вас уже есть что-то в интересующих вас регионах.
Второй вариант — запуск недолговечных облачных виртуальных машин в целевых регионах с помощью таких провайдеров, как DigitalOcean или Hetzner. Этот вариант хорошо подходит для периодических или разовых тестов, хотя каждый раз, когда вы хотите провести проверку, требуется время на настройку и отключение.
Третий вариант, подходящий для команд, которые не хотят выделять и обслуживать тестовые серверы в каждом регионе, — это маршрутизация тестового трафика через географически распределенные прокси-серверы. В некоторых сценариях тестирования выделенные ротационные прокси могут обеспечить контролируемый пул региональных конечных точек для повторных проверок без необходимости управлять отдельной инфраструктурой в каждом регионе.
Каждый вариант предполагает компромисс между контролем, сложностью настройки и частотой проведения тестов. Выберите тот вариант, который соответствует частоте проверки производительности и количеству регионов, которые вам нужно охватить.
Создание воспроизводимого теста
Как только вы научитесь отправлять запросы из нескольких регионов, объедините все, что было сделано до этого, в один скрипт. Для каждого запроса записывайте:
- временную метку
- регион
- код состояния HTTP
- удаленный IP-адрес
- время DNS
- время подключения
- время TLS
- TTFB
- общее время
Простой выходной формат может выглядеть следующим образом:
timestamp,region,status,remote_ip,dns,connect,tls,ttfb,total 2026-09-05T09:00:00Z,eu-west,200,104.16.1.1,0.012,0.034,0.089,0.145,0.210 2026-09-05T09:00:00Z,ap-southeast,200,104.16.2.5,0.028,0.061,0.140,0.310,0.402
Вы можете перенаправить этот вывод в CSV-файл, легковесную базу данных, например SQLite, или в систему мониторинга, например Prometheus. Запуск скрипта по расписанию с помощью cron превращает разовую проверку в непрерывный мониторинг производительности с течением времени.
Интерпретация результатов
После того как вы соберете данные по нескольким запросам и регионам, используйте следующие закономерности для проведения расследования:
- Высокое время DNS: проверьте конфигурацию DNS и производительность резолвера.
- Высокое время подключения, нормальное время DNS: проверьте расстояние до сети и маршрутизацию в этот регион.
- Высокое время до первого байта, нормальное время подключения: проверьте обработку на CDN или исходном сервере, а также состояние кэша.
- Низкое время до первого байта, высокое общее время: проверьте размер ответа и скорость передачи.
- Один регион стабильно работает медленнее других: проверьте маршрутизацию, DNS-направление и покрытие CDN в этом регионе.
- Высокая вариативность между повторными запросами: ориентируйтесь на закономерность, выявленную при анализе множества запросов, а не на один результат.
Это превращает необработанные данные в отправную точку для реального устранения неполадок.
Что curl вам не расскажет
У тестирования через командную строку есть ограничение, о котором стоит четко заявить. curl измеряет производительность сети и HTTP-уровня. Оно не запускает JavaScript, не отображает страницы, не загружает изображения в том порядке, в котором это делает браузер, и не измеряет сдвиги макета.
Это означает, что тестирование через командную строку не может полностью заменить тестирование производительности в браузере. Оно дополняет его. Используйте curl для выявления проблем на уровне сети и сервера. Используйте браузерные инструменты, например инструменты разработчика вашего браузера или сервис синтетического мониторинга, чтобы оценить пользовательский опыт в целом, включая рендеринг и поведение на стороне клиента.
Краткий справочник
| Инструмент | Что он измеряет | Пример команды |
|---|---|---|
curl -w | Анализ времени выполнения запроса | curl -o /dev/null -w '%{time_total}\n' URL |
curl -D - | Заголовки ответа, статус кэша | curl -s -o /dev/null -D - URL \| grep -iE '(cache\|age)' |
curl --http3 | Сравнение HTTP/3 (QUIC) и HTTP/2 | curl -o /dev/null -w '%{http_version}\n' --http3 URL |
dig | Разрешение DNS | dig example.com |
curl -4 / curl -6 | Производительность IPv4 и IPv6 | curl -4 -o /dev/null -w '%{time_total}\n' URL |
Заключение: измеряйте то, с чем на самом деле сталкиваются пользователи
CDN не будет работать просто потому, что она включена. Главный вопрос заключается в том, быстро ли и стабильно ли она доставляет ваш контент пользователям в тех местах, где они живут.
Рабочий процесс, описанный в этом руководстве, строится по простому принципу: измерение, проверка, повторение, сравнение, диагностика и повторное измерение. Начните с одного запроса на своем компьютере. Проверьте, действительно ли CDN выполняет кэширование. Повторите тест, чтобы исключить случайные ошибки.
Затем примените тот же метод к нескольким регионам, используя собственную инфраструктуру, облачные тестовые машины или распределенные прокси-конечные точки — в зависимости от того, как часто вам нужно проводить проверку и сколько регионов охватить.
Инструменты командной строки позволяют выполнять весь этот рабочий процесс без платного программного обеспечения для мониторинга. Единственное, что требуется, — выработать привычку проверять.
Редактор: AndreyEx