Команда хочет измерять задержку, которую испытывает пользователь. В этом фрагменте таймер запускается после получения соединения из клиентского пула. Какой показатель искажается и где нужно начинать измерение?
connection = pool.acquire()
start = monotonic()
response = connection.send(request)
elapsed = monotonic() - start
pool.release(connection)
Измеряется только время выполнения запроса после получения соединения, а ожидание соединения в клиентском пуле исключается. Для пользовательской задержки таймер нужно запускать до pool.acquire(), а останавливать после полного получения ответа и выполнения клиентской обработки, входящей в пользовательский сценарий.
Нагрузочные тесты используют несколько временных границ измерения, потому что задержка может возникать на разных участках: в генераторе нагрузки, пуле соединений, сети, сервере или при чтении ответа. Разделение этих участков появилось как практический способ отличать время обработки на сервере от времени, которое действительно наблюдает клиент.
Без явно заданной границы измерения команда может получить точный, но нерелевантный показатель. Например, серверное время будет нормальным, пока клиенты простаивают в очереди за ограниченным числом соединений.
Если таймер запускается после pool.acquire(), рост конкуренции за клиентский пул не попадёт в измеренную задержку. Отчёт может показать стабильный p95, хотя пользователи фактически ждут всё дольше.
Такое искажение особенно опасно, когда размер пула меньше числа виртуальных пользователей или когда генератор моделирует реального клиента с ограниченным числом соединений. Можно ошибочно решить, что сервис соблюдает SLA, увеличить нагрузку или выпустить новую версию, скрывающую проблему на стороне клиента.
Граница измерения должна соответствовать проверяемому вопросу. Для сквозной пользовательской задержки стартуют до всех действий, которые пользовательский клиент должен выполнить перед отправкой запроса, включая ожидание свободного соединения. Завершают измерение после получения полного ответа, если именно полный ответ определяет завершение операции.
В исходном коде интервал равен примерно следующей величине:
время отправки и обработки запроса + передача ответа после получения соединения.
В исправленном варианте дополнительно учитывается ожидание в пуле соединений. Это позволяет увидеть насыщение клиента-генератора, но не доказывает, что узкое место находится на сервере: очередь может возникать из-за слишком маленького пула, медленного чтения ответов или ограничений самого генератора.
Для диагностики полезно собирать раздельные компоненты: время ожидания соединения, сетевое время, серверное время и время чтения ответа. Серверный заголовок или трассировка могут показать обработку на сервере, но не заменяют клиентскую метрику: пользователь ждёт весь путь.
Нельзя бездумно включать в одну метрику время подготовки сценария, паузы между действиями пользователя и фоновые операции. Если SLA задан для конкретного API-вызова, измерение должно соответствовать именно этому контракту. Если SLA описывает пользовательский сценарий, измерять нужно весь сценарий, а не отдельный внутренний участок.
Нагрузочный тест интернет-магазина показывал стабильный p95 API около 180 мс. При этом после увеличения числа виртуальных пользователей пользователи в тестовом интерфейсе ждали больше секунды. Анализ показал, что генератор имел 100 соединений на 500 виртуальных пользователей, а таймер начинался только после выдачи соединения.
Команда рассматривала два варианта. Увеличение пула быстро уменьшало очередь, но могло перегрузить целевой сервис и скрыть ограничение, которое должен был выявить тест. Перенос таймера до получения соединения сохранял реальную пользовательскую задержку, но требовал отдельно проверить, не стал ли сам генератор узким местом.
Выбрали второй вариант и добавили метрики ожидания пула, загрузки генератора и серверного времени. В результате серверный p95 остался примерно прежним, а клиентский p95 резко вырос на высокой нагрузке. Это позволило корректно заключить, что тест достиг ограничения генератора, а не доказал деградацию серверного API.
Нет. Это правильно только для метрики, описывающей задержку клиента или пользователя. Для изолированного измерения серверной операции ожидание локального пула может быть намеренно исключено, но такую метрику нужно явно назвать серверной или сетевой, а не пользовательской.
Если операция считается завершённой только после получения полного тела, да. Измерение до получения заголовков характеризует время до начала ответа, но может скрыть медленную передачу большого тела, ограничение пропускной способности сети или задержки при потоковой выдаче.
Нет. Рост очереди означает конкуренцию за клиентский ресурс, но причина может быть локальной: маленький пул, блокировка генератора, медленное освобождение соединений или недостаточная мощность машины нагрузки. Нужно сопоставить эту метрику с серверными задержками, ошибками, утилизацией генератора и фактической скоростью отправки запросов.