Перейти к содержимому
Скачать
Все статьи
Руководства

Как мы ускорили Moove на 59%

Большинство пользователей Moove далеко от наших серверов. Как мы сократили время до первого ответа на 59%, не перенося серверы, и что оказалось сложнее всего.
6 нояб. 2026 г.9 мин чтения

Расстояние было нашей самой медленной зависимостью

Большинство людей, которые открывают Moove app, сидят в мобильных сетях Нигерии и Индонезии, в тысячах километров от серверов, которые им отвечают. В этом месяце мы изменили путь, которым их запросы доходят до нас, и наше время до первого байта (TTFB), то есть время между отправкой запроса телефоном и приходом первой части ответа, сократилось на 59%: с 0,74 секунды до 0,31 секунды. Для этого нам не пришлось переносить ни одного сервера.

В этой статье мы объясняем, почему расстояние обходилось нам дороже, чем мы ожидали, что именно мы изменили, какая часть оказалась сложнее самого изменения и что мы посоветовали бы другой команде, которая собирается сделать то же самое.

Почему одна длинная поездка превращается в три

Инженеры называют задержку между отправкой данных и их получением латентностью, а время, за которое сообщение доходит до сервера и возвращается ответ, временем кругового обхода (RTT). От Лагоса до наших серверов RTT составляет от 200 до 300 миллисекунд. Само по себе это терпимо. Проблема в том, что запрос редко путешествует в одиночку.

Прежде чем телефон сможет что-либо запросить по защищённому соединению, он должен пройти два рукопожатия, коротких обмена сообщениями, которые устанавливают соединение. Рукопожатие TCP открывает соединение, а затем рукопожатие TLS согласует ключи шифрования, которые сохраняют его конфиденциальность. Каждое стоит полного кругового обхода. Только после этого уходит сам запрос, и это третья поездка. При 250 миллисекундах на поездку пользователь ждёт примерно три четверти секунды, прежде чем наши серверы успеют выполнить хоть какую-то работу.

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

Мы не могли приблизить Лагос к нашим серверам. Зато мы могли приблизить установку соединения к Лагосу.

Переносим рукопожатие, а не серверы

Сеть доставки контента (CDN) обычно описывают как кэш: набор площадок по всему миру, которые хранят копии файлов, чтобы отдавать их с ближайшей. Мы использовали её по другой причине. Для нашего API, интерфейса, через который приложение выполняет всё, что делает, кэширование полностью отключено. Каждый запрос по-прежнему идёт к нашему origin, так CDN называет серверы, стоящие за ней.

Меняется то, где начинается соединение. Теперь телефон открывает соединение с ближайшей периферийной площадкой, которую также называют точкой присутствия (PoP): одним из узлов CDN по всему миру, часто находящимся в десятках миллисекунд от пользователя, а не в сотнях. На периферии выполняется терминация TLS, то есть защищённое соединение с телефоном заканчивается именно там. Затем она переиспользует пул тёплых соединений с нашим origin, которые поддерживаются открытыми с помощью keep-alive, настройки, оставляющей соединение открытым между запросами вместо того, чтобы закрывать его. Две дорогие установочные поездки происходят на коротком участке, а через океан идёт только сам запрос, по уже тёплому соединению.

Три длинные поездки превращаются в одну длинную и две короткие. В этом вся идея.

Всё остальное мы намеренно сделали скучным:

  • Клиенты ничего не заметили. Приложение и сайт сохранили прежние адреса, поэтому выпускать новую версию приложения не потребовалось, и никому ничего не пришлось обновлять.
  • Поведение при сбоях осталось прежним. Тайм-ауты совпадают с прежними, поэтому всё, что раньше давало сбой, ломается точно так же. Новых видов ошибок мы не хотели.
  • Периферия первой закрывает простаивающие соединения. У каждого соединения есть тайм-аут простоя, то есть время, которое оно может бездействовать до закрытия. Если бы наши серверы закрыли тихое соединение, пока периферия всё ещё считает его открытым, следующий запрос завершился бы ошибкой. Если задать тайм-аут периферии короче, она всегда сдаётся первой и открывает новое соединение.
  • Более новые протоколы для телефонов. Телефоны могут подключаться по HTTP/3, новейшей версии веб-протокола запросов. Он работает поверх QUIC, который объединяет оба рукопожатия в один круговой обход и лучше справляется с потерей пакетов, обычной для мобильных сетей.
  • Ни один регион не пропущен. Более дешёвые тарифы периферийных сетей часто пропускают площадки именно в тех частях мира, где живут наши пользователи, поэтому мы выбрали полное покрытие.

Что мы измерили

Мы измеряли из Сиднея, который находится примерно так же далеко от наших серверов, как Лагос, сравнивая старый путь с новым. Для каждого мы открывали по пять новых холодных соединений, случай, который важнее всего в мобильных сетях, и брали медиану, также обозначаемую p50: срединный результат, который лучше, чем у половины запросов, и хуже, чем у другой половины. В рамках того же проекта мы также включили сжатие для скриптов нашего сайта, которые раньше отправлялись в полном размере. Сжатие уменьшает файл перед отправкой, а браузер разворачивает его обратно по прибытии; мы использовали Brotli, формат сжатия, созданный для веба.

Что мы измерялиДоПослеУлучшение
Рукопожатия TCP и TLS завершены (p50)490 ms59 msбыстрее на 88%
Время до первого байта (p50)743 ms307 msбыстрее на 59%
Объём скриптов главной страницы1.76 MB560 KBменьше на 68%

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

Эти цифры получены в одном городе и не являются глобальным эталонным тестом. Однако расчёт переносится на Лагос и Джакарту, а именно там находятся наши пользователи.

Самым сложным было понять, кто обращается

Поставить что-то перед своими серверами несложно. Сохранить работоспособность защитных механизмов за этим слоем — вот на что ушла большая часть усилий.

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

Решение опирается на две идеи.

Доверяйте ровно тем слоям, которые у вас есть. CDN — это разновидность обратного прокси, сервера, который стоит перед вашим и передаёт запросы дальше. Каждый прокси добавляет адрес, с которого получил запрос, в стандартный заголовок X-Forwarded-For, поэтому настоящий отправитель находится на фиксированное число шагов, или переходов, назад в этом списке. Ошибка в этом числе — баг в обе стороны. Если насчитать слишком мало слоёв, каждый пользователь будет выглядеть как его периферийная площадка. Если слишком много, вы начнёте доверять записи, которую отправитель написал сам. Поэтому мы сделали это число свойством инфраструктуры, а не кода. Оно меняется в тот же момент, что и сеть, а наш сервис отказывается запускаться, если значение лишено смысла, вместо того чтобы гадать.

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

Баг, который мы поймали до выпуска

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

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

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

Общий урок: добавляя слой, который очищает входные данные, найдите всё, что зависело от тех данных, которые вы собираетесь очистить.

Как мы выкатывали изменения

В платёжной инфраструктуре не бывает подхода «развернём и посмотрим», поэтому мы сначала изменили стейджинг, а потом продакшен, и несколько решений сделали переключение спокойным. Мы уменьшили TTL (время жизни) наших записей DNS, интернет-справочника, который превращает имя вроде moove.xyz в адрес сервера. TTL определяет, как долго остальной интернет может кэшировать этот ответ, и мы сократили его с часа до пяти минут за целый час до того, как что-либо сдвинулось, чтобы старый ответ везде устарел, а откат вступил в силу за считаные минуты. Адресные записи мы хранили в форме, которую можно переключить на месте, потому что их удаление и повторное создание оставило бы разрыв, а разрыв — это простой. Каждый рискованный шаг был отдельным небольшим изменением, а шаги для его отмены были записаны по порядку.

Что мы посоветовали бы другой команде

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

  • Составьте список всего, что читает адрес отправителя, включая лимиты запросов, списки разрешённых адресов, сигналы мошенничества, журналы аудита и правила безопасности. Каждый из них видит адрес периферии, пока вы это не измените.
  • Сделайте число доверенных слоёв частью инфраструктуры и откажитесь запускаться, если оно неверно.
  • Пусть периферия записывает настоящего отправителя, и доверяйте этой записи только в трафике, о котором можете проверить, что он пришёл с вашей периферии.
  • Убедитесь, что ваши серверы принимают трафик только через периферию, и наблюдайте, прежде чем включать принудительное применение.
  • Если вы кэшируете страницы, стройте ключ кэша, набор сведений о запросе, по которому кэш решает, могут ли два запроса делить один сохранённый ответ, из всего, от чего ответ действительно зависит. Серверы перечисляют эти сведения в заголовке Vary, поэтому читайте его, а не полагайтесь на память.
  • Измеряйте до и после и смотрите на время рукопожатия и время до первого байта по отдельности, чтобы отличить установку соединения от времени, которое тратят ваши серверы на работу.

Взгляд вперёд

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

Деньги должны двигаться со скоростью сети, а не со скоростью света через океан.

Если вы разрабатываете на основе Moove, прочитайте наше введение в платёжные API и SDK Web3 и Moove Developer Program.

Автор: инженерная команда moove.xyz.

О moove.xyz

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

Мы одна из первых Web3 финтех-компаний в мире, которая внедряет и строит полноценную инфраструктуру криптоплатежей и децентрализованных финансов, обеспечивая интегрированное и всестороннее покрытие доступа к мультисетевым кошелькам, персонализированным хэндлам кошельков, кросс-чейн свапам токенов, встроенным кросс-чейн транзакциям и децентрализованной социальной финансовой сети. Наши ключевые продукты включают Moove Profile, Moove Send, Moove Receive, Moove Stake, Moove Swap, Moove Rewards, Moove Discover и другие.

Наша миссия проста — создать и распространить безразрешительные и простые финансовые технологии для следующего 1 миллиарда пользователей Web3. Мы фундаментально убеждены, что будущее движения денег и ценности будет без затрат, без границ, без разрешения, без усилий и создано для всех — и мы строим идеальную Web3 финтех-платформу, чтобы сделать это будущее реальностью.

Ваши деньги. Ваш ход.

Читайте также.

Web3 Payment API и SDK: разработка на Moove
Руководства

Web3 Payment API и SDK: разработка на Moove

16 июл. 2026 г.9 мин чтения
Всё, что нужно знать о Moove Developer Program
Руководства
Заработок

Всё, что нужно знать о Moove Developer Program

6 сент. 2026 г.8 мин чтения
Moove App: криптоплатежи для iOS и Android
Мнения

Moove App: криптоплатежи для iOS и Android

28 мар. 2026 г.7 мин чтения

Ваши деньги. Ваш ход.

Отсканируйте, чтобы загрузить приложение Moove
Загрузить в App StoreДоступно в Google Play