Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Golang: latency, percentile, p99

Как обеспечить время ответа backend-сервиса менее 100 мс при высоком RPS?

Вопрос проверяет, понимаете ли вы, из чего складывается latency, и умеете ли проектировать быстрый путь обработки: минимальные зависимости, кэш/предрасчёт, ограничения параллелизма и контроль хвостовых задержек (p95/p99).

Короткий ответ

Сначала нужно “вписаться” в бюджет времени: сеть, сериализация, бизнес-логика, БД и внешние вызовы. Для <100 мс обычно убирают тяжёлые операции из запроса: предрасчёт, кеш, асинхронная обработка. Затем ограничивают вариативность: таймауты, лимиты, отказ от лишних сетевых прыжков. Обязательно оптимизируют доступ к данным (индексы, короткие запросы, батчи) и следят за p95/p99, а не только за средним временем. Без наблюдаемости и нагрузочного теста это не удержать.

Длинный ответ

Откуда берётся 100 мс

100 мс — это общий бюджет на весь путь: клиент → сеть → сервис → зависимости → ответ. Обычно “съедают” время именно зависимости, поэтому быстрый сервис — это сервис с минимальным количеством непредсказуемых вызовов.

1) Бюджет времени и цель по перцентилям

Нужно сразу определить:

  • целевой перцентиль (например, p95 < 100 мс, p99 < 200 мс)

  • максимальное число сетевых hops (чем меньше, тем лучше)

Определение: Percentile (p95/p99) — время, быстрее которого укладывается 95%/99% запросов; это главный показатель “хвостовой” задержки.

2) Сократить работу в запросе

Типовые приёмы:

  • предрасчёт и хранение готовых результатов

  • кэширование (частей ответа или всего ответа)

  • перенос тяжёлых операций в фон (очередь/воркеры)

Если данные “почти всегда уникальны”, кэш может быть не по полному ответу, а по его частям:

  • справочники/права/настройки

  • данные профиля

  • результаты дорогих вычислений, которые переиспользуются между запросами

3) Оптимизировать доступ к данным

С БД важно:

  • короткие запросы (без лишних join/scan)

  • индексы под реальные фильтры

  • ограничение объёма выборки (пагинация, лимиты)

  • пул соединений адекватного размера

4) Ограничить параллелизм и защитить зависимости

Под высоким RPS легко “убить” БД лавиной параллельных операций.

Практика:

  • лимит параллельных запросов к БД/внешним сервисам

  • таймауты на каждый вызов

  • деградация (лучше частичный ответ, чем 500)

Пример таймаута и отмены через context:

ctx, cancel := context.WithTimeout(r.Context(), 80*time.Millisecond)
defer cancel()

// db.QueryContext(ctx, ...)

5) Уменьшить накладные расходы в Go

В Go типичные источники потерь:

  • лишние аллокации на горячем пути

  • большие JSON payload и частая сериализация

  • слишком подробное логирование на каждый запрос

Практика:

  • профилировать pprof (CPU/heap)

  • избегать лишних преобразований структур

  • аккуратно с middleware, которые делают много работы

6) Наблюдаемость и нагрузочные тесты

Чтобы удерживать SLA, измеряйте:

  • latency p50/p95/p99

  • долю таймаутов и ретраев

  • latency по каждой зависимости

  • насыщение пулов (goroutines, DB pool)

Вывод

Стабильные <100 мс при высоком RPS достигаются не “быстрым кодом”, а архитектурой быстрого пути: минимум зависимостей в запросе, предрасчёт/кэш, строгие таймауты и лимиты, плюс контроль p95/p99 и постоянное профилирование.

  • Аватар

    Golang Guru

    Maxim Lukyanov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    5

  • Сложность:

    8

Навыки

  • Golang

    Golang

Ключевые слова

#latency

#percentile

#p99

Подпишись на Golang Developer в телеграм

  • Аватар

    Golang Guru

    Maxim Lukyanov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.