АрхитектураПроектирование системИнженер по разработке backend-систем

Команда требует: «система должна отвечать быстро». Как превратить это требование в проверяемое ограничение?

Команда требует: «система должна отвечать быстро». Как превратить это требование в проверяемое ограничение?

Проходите собеседования с ИИ помощником Hintsage

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

Нужно заменить слово «быстро» измеримым условием: указать конкретную операцию, границу измерения, профиль нагрузки и допустимую задержку с выбранным процентилем. Например: «95% запросов на получение карточки товара должны завершаться не дольше 300 мс при 500 запросах в секунду и размере ответа до 50 КБ».

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

Исторический контекст

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

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

Постановка проблемы

Фраза «система должна отвечать быстро» не говорит, о каком API идёт речь, считается ли время от клиента или от сервера, какая доля запросов должна укладываться в предел и при каком трафике действует требование.

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

Подробное решение

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

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

Задержку следует описывать процентилем. Условие p95 ≤ 300 мс означает, что не менее 95% измеренных запросов укладываются в 300 мс; оно не ограничивает оставшиеся 5%. p99 предъявляет более жёсткое требование к хвосту распределения, но может быть чувствителен к объёму выборки и редким внешним сбоям.

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

Формулировка должна содержать критерий результата и способ проверки. Например: «Для операции поиска при 1000 запросах в секунду, распределении 80% коротких и 20% сложных запросов, p95 серверной задержки не превышает 400 мс, а доля ошибок не превышает 0,1%».

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

Ситуация из практики

В каталоге интернет-магазина команда зафиксировала требование «поиск должен быть быстрым». Один вариант — принять среднюю задержку не более 100 мс. Он прост для контроля, но скрывает ситуацию, при которой большинство запросов быстрые, а сложные фильтры систематически задерживаются на секунды.

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

Команда выбрала условие p95 не более 300 мс при явно заданном профиле поиска и отдельно установила ограничение p99 не более 800 мс для контроля хвоста. Измерение проводилось на границе сервиса, а клиентский показатель отслеживался отдельно, потому что сетевые задержки и время отрисовки не контролируются только сервером.

После этого нагрузочный тест стал воспроизводимым: команда увидела, что средняя задержка соответствует цели, но p99 растёт из-за запросов с редкими фильтрами. Оптимизация индекса улучшила именно хвост, а не только среднее значение, и решение принималось на основании проверяемого критерия.

Что кандидаты часто упускают

  1. Почему нельзя ограничиться средней задержкой?

Среднее значение агрегирует все запросы в одно число и может скрыть плохой опыт небольшой доли пользователей. Например, если 99% запросов выполняются за 50 мс, а 1% — за 5 секунд, средняя задержка будет около 99,5 мс, хотя каждый сотый запрос явно медленный.

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

  1. Что изменится, если измерять задержку на границе сервиса вместо полного пользовательского пути?

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

Поэтому обычно разделяют два показателя: server-side latency для контроля самого сервиса и end-to-end latency для сценария пользователя. Нельзя подменять один показатель другим: сервер может выполнять запрос за 100 мс, а пользователь получать результат через 600 мс из-за внешних этапов.

  1. Как поступить, если разные операции имеют разную сложность?

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

Нужно разделить требования по endpoint, типу операции или классу запроса и определить профиль каждого класса. Допустимо задать разные цели: например, для простого чтения — p95 до 100 мс, для сложного поиска — p95 до 500 мс. Это делает измерение честным, но увеличивает число метрик и стоимость наблюдения, поэтому деление должно соответствовать реальным пользовательским сценариям.