Сервис замедляется, пока один ресурс первым достигает высокой утилизации. Как подтвердить, что именно он является узким местом?
Высокая утилизация сама по себе не доказывает наличие узкого места: ресурс может быть занят из-за задержек в другом компоненте. Узкое место подтверждается причинным экспериментом: если временно увеличить его пропускную способность или снизить его загрузку, а задержка и пропускная способность системы заметно улучшатся, это сильное доказательство.
Нужно сопоставить временные ряды утилизации, очередей, задержек и ошибок, а затем проверить гипотезу изменением только предполагаемого ресурса. Если изменение не влияет на результат, ресурс, вероятно, является следствием перегрузки или не ограничивает текущий сценарий.
По мере усложнения систем одной метрики стало недостаточно для объяснения деградации производительности. В распределённых приложениях запрос проходит через несколько уровней: генератор нагрузки, сеть, балансировщик, приложение, базу данных и внешние зависимости.
Подход с поиском узкого места нужен, чтобы перейти от наблюдения «система медленная» к проверяемой причине. Он помогает отличить ограничение мощности конкретного компонента от вторичных эффектов, например простаивания CPU из-за ожидания базы данных.
При росте нагрузки обычно одновременно меняются несколько показателей: утилизация ресурса, длина очереди, время ответа, пропускная способность и доля ошибок. Если выбрать узким местом первый ресурс с высокой утилизацией, можно оптимизировать компонент, который не ограничивает общую производительность.
Неверный вывод приводит к бесполезному масштабированию, росту расходов и переносу ограничения в другой слой. Например, увеличение числа экземпляров приложения не устранит задержку, если запросы всё ещё ждут исчерпанные соединения с базой данных.
Сначала формулируют гипотезу: конкретный ресурс ограничивает обработку запросов. Затем проверяют, согласуется ли она с наблюдениями: у ресурса должна расти не только утилизация, но и связанная с ним очередь или время ожидания, а изменение этого состояния должно совпадать с ухудшением пользовательских метрик.
Ключевая проверка — эксперимент с вмешательством. Можно временно увеличить доступную мощность ресурса, уменьшить стоимость операции, изменить размер пула или ограничить поток запросов к нему. Если при сопоставимой входной нагрузке растёт пропускная способность, снижаются задержки или исчезают ошибки, гипотеза получает подтверждение.
Важно менять один фактор за раз и повторять тест в сопоставимых условиях. Иначе улучшение может быть вызвано прогревом кэша, изменением профиля нагрузки, освобождением другого ресурса или случайными колебаниями.
Утилизация должна интерпретироваться вместе с очередями и ожиданием. Высокая загрузка CPU при короткой очереди может быть нормальным эффективным использованием ресурса, тогда как высокая загрузка с растущей очередью указывает на нехватку обслуживающей способности.
Есть и обратная ситуация: низкая утилизация CPU не исключает узкое место. Потоки приложения могут блокироваться на вводе-выводе, лимите соединений, синхронизации или внешнем сервисе, поэтому необходимо измерять именно тот ресурс, за которым фактически ожидают запросы.
Практический компромисс состоит в стоимости диагностики. Детальная трассировка помогает установить причинную связь, но добавляет накладные расходы; агрегированные метрики дешевле, однако могут скрыть кратковременные пики и различия между отдельными запросами.
Во время теста API задержка растёт после достижения 70 процентов загрузки приложения. Команда рассматривает три варианта: увеличить число экземпляров приложения, увеличить пул соединений к базе данных или уменьшить объём диагностического журналирования.
Масштабирование приложения имеет плюс — оно быстро проверяет гипотезу о нехватке вычислительной мощности, но может не помочь при общем лимите базы данных. Увеличение пула соединений способно сократить ожидание, однако при уже перегруженной базе данных оно лишь усилит конкуренцию. Снижение журналирования уменьшит нагрузку на ввод-вывод, но может осложнить диагностику и не затронуть основную причину.
По метрикам видно, что CPU приложения умеренный, очередь запросов к базе данных растёт, а увеличение пула в отдельном тесте не улучшает задержку. Команда временно добавляет реплику для операций чтения и повторяет тест при том же профиле запросов.
После изменения очередь и p95 снижаются, а пропускная способность растёт без заметного увеличения ошибок. Это подтверждает, что ограничением был путь чтения из базы данных, а не вычислительная мощность приложения; дальнейшая оптимизация CPU не дала бы сопоставимого эффекта.
Нет. Утилизация показывает занятость, но не причинность. Ресурс может быть занят обработкой работы, которая сама возникла из-за ограничения в другом компоненте, поэтому нужны признаки очереди, ожидания и результат контролируемого изменения.
Например, высокий CPU приложения может быть следствием повторных попыток обращений к недоступной зависимости. Снижение нагрузки на эту зависимость или устранение повторных попыток должно изменить CPU приложения, хотя приложение не было исходным ограничением.
Нужно контролировать сам генератор: его CPU, память, сетевой интерфейс, число открытых соединений и способность поддерживать заданный профиль запросов. Если при добавлении генераторов пропускная способность тестируемой системы растёт, прежний генератор был ограничением.
Также следует сравнить фактически отправленный поток с целевым. Если генератор не достигает целевой нагрузки, выводы о предельной мощности приложения делать нельзя: эксперимент проверял не заявленный сценарий, а меньший поток.
Это может означать, что ограничение было ошибочно определено, одновременно действовало несколько ограничений или система быстро упёрлась в следующий компонент. Нужно повторно построить картину загрузки и очередей после изменения, а не считать исходную гипотезу полностью подтверждённой.
Полезно оценить, какой ресурс стал следующим ограничителем и изменилась ли сама структура задержки. Устранение узкого места иногда только перемещает границу насыщения, поэтому итог оценивают по сквозным метрикам — задержкам, успешной пропускной способности и ошибкам, а не по улучшению одной локальной метрики.