Сервис отвечает «202 Accepted» сразу, а работу выполняет асинхронно. Как измерить его производительность, чтобы не принять скорость приёма за скорость выполнения?
Нужно разделять скорость принятия запросов и скорость завершения бизнес-операций. Помимо RPS ответов «202 Accepted», измеряют число фактически завершённых операций в единицу времени, глубину очереди, возраст самой старой задачи и сквозное время от постановки задачи до результата.
Если учитывать только ответы «202», тест может показать высокую производительность при постоянно растущей очереди и ухудшении пользовательского результата.
Асинхронная обработка появилась как способ быстро освободить клиентский запрос и перенести длительную работу в очередь или фоновые обработчики. Такой подход снижает время синхронного ответа и позволяет независимо масштабировать приём задач и их выполнение.
Из-за разделения этих этапов одной метрики HTTP-запроса стало недостаточно. Для оценки производительности потребовались показатели отдельных стадий и полного жизненного цикла операции.
Ответ «202 Accepted» означает, что система приняла запрос на дальнейшую обработку, но обычно не означает завершение самой операции. Если генератор считает успешным каждый такой ответ, он измеряет пропускную способность входного API, а не производительность очереди и обработчиков.
Опасный сценарий возникает, когда входной поток быстрее фоновых потребителей. RPS принятия остаётся высоким, HTTP-ошибок может не быть, но очередь растёт, результат приходит всё позже, а часть задач в итоге может истечь по сроку хранения или завершиться ошибкой.
Нагрузочный тест должен наблюдать несколько уровней метрик:
Для каждой тестовой операции нужен корреляционный идентификатор, позволяющий связать первоначальный запрос с последующим результатом. Завершённой следует считать не выдачу «202», а подтверждённое успешное окончание бизнес-операции.
В установившемся режиме входная и выходная скорости должны быть близки, а очередь не должна иметь устойчивого тренда роста. Если скорость принятия выше скорости завершения, система ещё может выглядеть быстрой по HTTP-метрикам, но фактически накапливает обязательства перед пользователями.
Важно отдельно задать критерии успеха: допустимое время завершения, максимальный размер очереди, предельный возраст задачи и допустимую долю неуспешных операций. Нельзя безоговорочно складывать пропускную способность API и обработчиков: это разные этапы конвейера.
В тесте сервиса импорта документов API стабильно принимал 500 задач в секунду и возвращал «202». Команда сочла результат успешным, но после завершения теста очередь продолжала расти, а фактическая скорость обработки составляла только 320 документов в секунду.
Рассматривались два варианта. Можно было увеличить число HTTP-экземпляров, но это повысило бы только скорость приёма и ускорило бы переполнение очереди. Можно было снизить входной поток до 320 задач в секунду, однако это не устраняло ограничение обработчиков и уменьшало достигнутую производительность.
Выбрали измерение полного цикла с корреляцией задач и масштабирование фоновых обработчиков после проверки их узкого места. В качестве критерия использовали стабильную глубину очереди, близкие скорости принятия и завершения, а также допустимое сквозное время. Такой результат отражал реальную способность системы выполнять операции, а не только быстро подтверждать их получение.
1. Вопрос: Достаточно ли равенства скорости принятия и скорости завершения в конце теста?
Нет. Равенство в одной точке не доказывает отсутствие накопленного долга: очередь могла вырасти ранее и ещё не успеть уменьшиться. Нужно анализировать временной ряд размера очереди, скорость её изменения и продолжать наблюдение после снижения нагрузки.
2. Вопрос: Почему среднее сквозное время может скрыть проблему асинхронного конвейера?
Среднее сглаживает хвост распределения. Большинство задач может завершаться быстро, пока небольшая, но важная доля надолго застревает в очереди. Поэтому нужны перцентили сквозного времени, возраст очереди и доля задач, завершившихся в установленный срок.
3. Вопрос: Как отличить медленные обработчики от недостаточной пропускной способности входного API?
Нужно сопоставить скорость принятия, скорость извлечения задач потребителями, время обработки одной задачи, глубину очереди и загрузку ресурсов обработчиков. Если API принимает задачи быстро, а потребители стабильно завершают меньше операций и очередь растёт, ограничение находится после приёма. Если же обработчики простаивают из-за низкой скорости постановки задач, искать проблему следует во входном контуре или генераторе нагрузки.