Как найти причину медленного API без случайных оптимизаций

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

Практическое решение · 4 мин чтения
Как найти причину медленного API без случайных оптимизаций — tarasovcode
РазработкаКак найти причину медленного API без случайных оптимизаций

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

Что подготовить

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

Порядок работы

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

Разобранный пример

В учебном примере полное время составляет 2400 мс: ожидание соединения занимает 1800 мс, SQL — 180 мс, остальные этапы — 420 мс. Оптимизация SQL на четверть сэкономит лишь 45 мс. Следующий эксперимент должен объяснить занятые соединения и время транзакций, а не начинаться с нового индекса.

Как проверить результат

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

Если что-то пошло не так

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

Промпт для разбора ваших материалов

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

Частые вопросы

Нужно ли сразу проводить нагрузочный тест?

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

Можно ли ориентироваться на среднее время?

Среднее скрывает редкие длинные ответы. Рассматривайте распределение вместе с ошибками и числом запросов в выборке.

Материал библиотеки решений Ильи Тарасова / TarasovWeb.

Как отличить очередь от медленной обработки

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

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

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

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

О проекте

Практическая библиотека Ильи Тарасова и TarasovWeb. Telegram-канал · Личная страница · ВКонтакте.

#tarasovweb #ИльяТарасов