Возьмём один HTTPS-запрос к API и запустим на нём воображаемый секундомер. Пока клиент ждёт, происходит сразу несколько разных вещей: он узнаёт адрес сервера, устанавливает соединение, договаривается о шифровании, отправляет запрос, ждёт, пока приложение что-то посчитает, и только потом получает ответ. Когда говорят «во Франции быстрее» или «в Великобритании быстрее», обычно имеют в виду один этап из этой цепочки, а спорят о всей цепочке целиком. Давайте разберём её по частям и посмотрим, какие из них вообще зависят от выбора страны.

Все числа ниже в статье условные и нужны только для того, чтобы показать логику расчёта. Это не результаты измерений какого-либо сервера и не обещание того, что вы увидите у себя.

Куда уходят миллисекунды одного запроса

Удобный инструмент для первого разбора — curl с выводом таймингов. В руководстве curl описаны переменные time_namelookup, time_connect и time_appconnect: они показывают, сколько времени прошло от начала операции до завершения разрешения имени, TCP-соединения и TLS-рукопожатия. Дальше идут time_starttransfer (момент до первого байта ответа, включая обработку запроса сервером) и time_total (полная длительность).

Важная деталь: эти значения накопительные. Каждое отсчитывается от начала операции, а не от конца предыдущего этапа. Поэтому их нельзя просто сложить: если time_connect равен 40 мс, а time_appconnect — 110 мс, то на TLS ушло примерно 70 мс, а не 110. Чтобы получить длительность отдельного этапа, нужно вычитать соседние значения.

Покажем это на условном примере. Допустим, клиент вывел такие накопительные значения:

Условный пример: накопительные значения и длительность этапов
ПоказательНакопительно, мсЭтап отдельно, мс
time_namelookup2020 (DNS)
time_connect6040 (TCP)
time_appconnect13070 (TLS)
time_starttransfer230100 (запрос, обработка, первый байт)
time_total24515 (передача тела ответа)

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

Разберём ту же таблицу ещё раз, но с вопросом: что здесь можно изменить переездом? Условные 40 мс на TCP и 70 мс на TLS в сумме дают 110 мс из 245. Это около 45% полного времени, и именно эта доля чувствительна к расстоянию. Интервал в 100 мс до первого байта включает работу приложения, поэтому приписывать его целиком сети нельзя: часть уйдёт на код, обращения к базе и очередь внутри процесса. DNS в 20 мс при повторных запросах обычно берётся из кэша резолвера и вообще может исчезнуть из счёта.

Теперь представим, что тот же сервис стоит в другой стране, а приложение и данные у него точно такие же. Тогда кандидаты на изменение — строки с TCP и TLS, а строка с обработкой остаётся прежней, если зависимости не сдвинулись. Если после переезда у вас изменилась именно она, значит, вы поменяли не только страну. Такое наблюдение полезнее самого итогового времени: оно сразу показывает, что в тест попал посторонний фактор.

Почему расстояние чувствуется в рукопожатиях

Каждый обмен в рукопожатии стоит примерно одного времени кругового пробега между клиентом и сервером. Если TCP-соединение и TLS-рукопожатие требуют нескольких таких обменов, то разница в сетевой дистанции умножается. Допустим, у клиента до одного узла круговой пробег условно 30 мс, а до другого — 45 мс. Разница в 15 мс на первый взгляд мала, но при двух-трёх обменах до отправки полезного запроса она превращается в 30–45 мс, и это уже заметная доля общего времени быстрого API.

Это рассуждение объясняет механику, но не отвечает, какая страна лучше. Ответ зависит от того, где находятся ваши клиенты, и от того, как они подключаются: напрямую, через мобильную сеть, через корпоративный шлюз или через CDN.

Первый запрос и жизнь на готовом соединении

Первое обращение клиента к API платит за всё: DNS, TCP, TLS, и только затем идёт сам запрос. Но если клиент держит соединение открытым и отправляет следующие запросы по нему, три первых этапа исчезают из счёта. Остаётся время до первого байта и передача ответа.

Отсюда важное следствие для сравнения двух локаций. Если ваш API вызывают мобильные приложения, которые открывают соединение один раз за сессию и делают десяток запросов, то страна сервера влияет на первый запрос сильно, а на остальные — только через время кругового пробега внутри самого запроса и ответа. Если же вызывающая сторона — короткоживущий скрипт или вебхук, который каждый раз устанавливает новое соединение, то стоимость рукопожатий присутствует в каждом обращении.

Поэтому замеры нужно делать минимум в двух режимах и сохранять их раздельно:

  • «холодный» запрос с новым соединением: здесь видны все этапы, и расстояние проявляется сильнее всего;
  • запрос по уже открытому соединению: здесь видно, насколько быстро приложение отвечает и как далеко от него до клиента в одном обмене.

Если смешать эти режимы в одну среднюю цифру, она не будет описывать ни одного реального пользователя.

Разберём на условных числах, как это выглядит в счёте. Пусть круговой пробег до сервера равен 40 мс, а до первого байта по готовому соединению приложение отвечает за 60 мс. Тогда запрос по открытому соединению занимает порядка 100 мс: один обмен на сам запрос и ответ плюс работа приложения. Холодный запрос добавляет к этому установку TCP и TLS, то есть ещё несколько обменов по те же 40 мс, и легко уходит за 200 мс. Теперь допустим, что другой узел даёт 55 мс пробега. На готовом соединении потеря составит 15 мс, а на холодном при трёх обменах до полезных данных уже около 45 мс плюс те же 15 мс на сам запрос. Одна и та же разница в расстоянии заметна в двух режимах по-разному.

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

Сравнение, в котором меняется только страна

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

Чтобы сравнение имело смысл, нужно закрепить условия:

  • одинаковая версия приложения и одинаковая конфигурация, включая число рабочих процессов;
  • одинаковый набор данных, желательно скопированный с одного источника;
  • одинаковые ресурсы виртуальной машины: число vCPU, объём памяти и тип диска;
  • одинаковое расположение зависимых сервисов или одинаковая схема доступа к ним;
  • один и тот же сценарий запросов и один и тот же клиент для измерения.

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

Где живёт база и внешние API

Расположение VPS не равно расположению всего, к чему приложение обращается. Допустим, ваш сервис получает запрос, идёт в управляемую базу в одном регионе, затем вызывает платёжный API третьей стороны, а после этого пишет в очередь. Перенос приложения из одной страны в другую меняет путь от клиента до приложения, но может не изменить пути от приложения до базы или внешнего сервиса. А иногда ухудшает его: если база осталась на прежнем месте, каждый запрос внутри обработки начинает платить за пересечение между странами.

Стоит учитывать и обратное: нельзя заранее считать, что внешний сервис одинаково доступен с любого IP-адреса или из любой страны. Это нужно проверять отдельно для каждой зависимости, а не предполагать.

Когда в обработке одного запроса несколько последовательных обращений к базе, расстояние между приложением и базой умножается на их число. Для такого случая есть технические приёмы: например, pipeline mode в libpq позволяет отправлять запросы, не дожидаясь результата предыдущего, и этим сокращает ожидание сетевых обменов. В документации же отмечено, что режим требует управления очередью результатов и может увеличивать расход памяти. То есть иногда выгоднее не менять страну, а уменьшить число обменов внутри приложения. Решает такой вопрос только замер на вашей нагрузке.

Если база и приложение находятся в одной локации, внутренний путь короткий и не зависит от выбора страны для клиентской стороны. Если они разнесены, нужно считать оба маршрута: клиент — приложение и приложение — база. Страна, лучшая для первого, может оказаться хуже для суммы.

Покажем это на условном примере. Приложение обрабатывает запрос за пять последовательных обращений к базе. Если база на том же VPS, каждое занимает доли миллисекунды сетевого времени. Если база осталась в другой стране и круговой пробег до неё условно 20 мс, то пять обращений добавляют около 100 мс к каждому ответу, независимо от того, насколько хорошо клиент подключается к приложению. Выигрыш в 15 мс на пути клиента от переезда тут просто теряется.

Отсюда правило для сравнения: считайте число обращений на один запрос и умножайте его на пробег до каждой зависимости. Если сумма велика, сначала сократите число обменов или перенесите зависимость ближе, и только потом сравнивайте страны. Иначе вы будете измерять не расположение VPS, а расстояние до базы.

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

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

АРЕНДОВАТЬ СЕРВЕР

Редкие медленные ответы важнее среднего

Среднее время ответа — удобная цифра, но для API она обманчива. Допустим, 98 запросов из 100 укладываются в 120 мс, а два занимают по 1,5 секунды. Среднее окажется около 150 мс, и выглядит это вполне прилично. Но пользователь, которому достался один из медленных ответов, этого среднего не видел. А если страница делает десяток запросов подряд, вероятность встретить медленный выше, чем кажется по одному запросу.

Поэтому сравнивать две локации нужно по распределению: медиана, высокие перцентили (например, 95-й и 99-й) и доля ошибок. Две локации с одинаковой медианой могут сильно различаться хвостом. Причины хвоста бывают разные: потеря пакетов и повторная передача, пауза сборщика мусора в приложении, соседняя нагрузка, перегруженный резолвер. Не все они зависят от страны, и именно повторные замеры в разное время суток показывают, что в хвосте случайность, а что системное.

Практичный способ зафиксировать критерии заранее — задать пороги. В документации Grafana k6 thresholds описаны как условия прохождения теста по метрикам, например по задержке или частоте ошибок; если условие не выполнено, тест считается неуспешным. Это удобно для честного сравнения: вы формулируете требование до замера, а не подбираете его под победителя. Значения порогов должны исходить из потребностей вашего приложения, а не из примеров в документации — эти примеры не являются нормативом для конкретного сайта.

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

Полезно заранее решить, как читать хвост при сравнении двух узлов. Допустим, на обоих медиана одинакова, а 99-й перцентиль у одного вдвое больше. Первым делом проверьте, когда появляются медленные ответы. Если они сгруппированы в определённые часы или приходят из одной точки запуска, причина, скорее всего, в пути или соседней нагрузке. Если они разбросаны равномерно по всем точкам, посмотрите на приложение: паузы процесса и сборка мусора не зависят от страны.

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

Какой этап на самом деле зависит от страны

Теперь вернёмся к разложению запроса и пройдём по этапам, спрашивая для каждого: меняется ли он при переезде из Франции в Великобританию или обратно?

  • DNS. Время разрешения имени определяется скорее резолвером клиента и настройками кэширования, чем местом сервера. Страна VPS почти не влияет, если только вы не размещаете там же собственный DNS.
  • TCP-соединение. Зависит от пути между клиентом и сервером. Здесь страна важна, но результат определяется маршрутом провайдера клиента, а не картой.
  • TLS. Цена рукопожатия складывается из сетевых обменов, так что расстояние умножается. Сокращать её помогает повторное использование соединений и возобновление сессий, но это настройки, а не география.
  • Ожидание ответа приложения. Определяется кодом, базой, кэшем и ресурсами машины. Страна влияет лишь опосредованно — через расстояние до зависимостей.
  • Передача тела. Зависит от размера ответа, сжатия и качества канала. При небольших ответах вклад мал.

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

Как провести сравнение руками

Рабочий порядок можно уложить в несколько шагов:

  1. Определите, откуда приходят ваши реальные запросы: страны, типы клиентов, долгоживущие или короткие соединения.
  2. Разверните одинаковое приложение на двух VPS с одинаковыми ресурсами, по одному в каждой локации, с одинаковыми данными.
  3. Выберите один сценарий, который отражает реальное использование, и один и тот же клиент измерения.
  4. Измеряйте отдельно холодный запрос и запрос по готовому соединению, сохраняя все накопительные значения таймингов.
  5. Повторяйте замеры в разное время суток и в разные дни, чтобы отделить системные различия от случайных.
  6. Сравнивайте по медиане, высоким перцентилям и доле ошибок, а не по среднему.
  7. Проверьте отдельно путь до каждой внешней зависимости из каждой локации.

Для такого стенда подходит VPS с понятными ресурсами. У MAATRIX в публичном предложении перечислены локации UK, US, RU и FR, поэтому французский и британский узлы можно сравнивать на одной платформе. Ресурсы тарифов, от Ba с 1 vCPU, 2 ГБ RAM и 40 ГБ NVMe до Djed с 16 vCPU и 32 ГБ, служат отправной точкой для теста, а не обещанием ёмкости: сколько запросов выдержит приложение, покажет ваша нагрузка. Для сравнения берите один и тот же тариф в обеих локациях, чтобы разница не пришла от ресурсов. Наличие конкретных образов и ОС в каждой локации стоит уточнить в форме заказа.

Если вы ещё присматриваетесь к зарубежным площадкам и хотите сопоставить ресурсы и локации у разных провайдеров, пригодится обзор LikeVPS с тарифами во Франции — как материал для сравнения набора ресурсов, а не готовый ответ на вопрос о задержке.

Разбор условного решения

Представим воображаемую ситуацию: сервис отдаёт небольшие JSON-ответы, соединения клиентов недолговечные, а база находится на том же VPS. Холодный запрос с новым соединением показывает, что рукопожатия занимают заметную долю времени, а ожидание приложения невелико. В таком случае улучшение сетевого пути от клиента к серверу напрямую отражается на полном времени запроса, и локация, которая ближе к большей части аудитории, выигрывает по тому этапу, который здесь доминирует.

Теперь другой воображаемый вариант: каждый запрос делает несколько обращений к внешнему сервису, который отвечает медленно, а ответы тяжёлые. Здесь сетевые этапы до сервера — малая часть общего времени, и разница между двумя соседними странами теряется на фоне ожидания зависимости. Выбор локации можно делать по другим соображениям, а время потратить на уменьшение числа внешних вызовов, кэширование или работу с соединениями.

Оба рассуждения условны и показывают метод, а не готовый результат. Реальные цифры у вас будут другими, и именно они должны определять решение.

Выбор, который улучшает нужный этап

Вопрос «Франция или Великобритания» сам по себе плохо поставлен, пока не названо, какой этап вашего запроса вы хотите ускорить. Если это установка соединения для клиентов из определённого региона, выбирайте узел, который показал лучшие TCP- и TLS-этапы и более короткий хвост из тех точек, где живёт ваша аудитория. Если основное время уходит на ожидание приложения или базы, сначала разберитесь с ними, а страну выбирайте по тому, где проще разместить сервис вместе с зависимостями. Если важна стабильность, ориентируйтесь на высокий перцентиль и долю ошибок по повторным замерам, а не на лучший одиночный результат.

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