Сценарии отказов¶
На карте есть пульт, и его кнопки ломают сервис по-настоящему. Смысл не в развлечении: наблюдаемость проверяется только отказом. Дашборд, на котором никогда не было аварии, — это картинка, а не инструмент.
Каждый сценарий выключается сам не позже чем через десять минут, ограничен двенадцатью запусками в минуту на весь стенд и затрагивает только приложение.
Утечка памяти¶
Что делает. Приложение начинает удерживать ссылки на блоки по 3 МБ и перестаёт их отпускать — до предела 256 МБ. Предел подобран так, чтобы балласт не уместился в кучу (325 МБ при обычном расходе 80–100 МБ), но и не вывел под за предел памяти контейнера: иначе память кончилась бы на всём узле, и вытеснять пришлось бы не только виновника.
Сценарий действует только на ту реплику, которая приняла запрос. Это намеренно: вторая продолжает обслуживать посетителей, и на дашборде видно, как расходятся показатели двух подов.
Что видно на дашборде.
- Куча растёт ступеньками и не опадает после сборки мусора. Это главный признак утечки: при пике нагрузки уровень после сборки возвращается к обычному, при утечке — нет.
- Доля времени в сборке мусора растёт: сборщик работает всё чаще, освобождая всё меньше.
- Опоздание такта карты увеличивается — паузы сборщика съедают то самое время, в которое нужно было рассылать кадр.
- На карте поезда начинают двигаться рывками. Именно так деградация выглядит для посетителя.
- Примерно через минуту виртуальная машина Java объявляет, что памяти нет.
Флаг
-XX:+ExitOnOutOfMemoryErrorзаставляет её завершиться сразу, а не пытаться работать дальше в невменяемом состоянии: контейнер перезапускается, и под возвращается в строй чистым. Оставшаяся реплика всё это время отвечает — бюджет допускающего сбои развёртывания не даёт увести обе разом.
Чему учит. Разница между утечкой и пиком видна в одной метрике — объёме живых данных после сборки мусора. Без неё спор «у нас утечка или просто нагрузка» решался бы гаданием.
Медленные ответы¶
Что делает. Обработчик добавляет 350 мс задержки к каждому запросу к API, кроме самого потока событий и управления сценариями.
Что видно.
- Перцентили времени ответа уезжают вверх, 95-й пробивает границу 300 мс.
- Доля быстрых ответов падает — начинается расход бюджета ошибок по задержке.
- Через несколько минут число реплик растёт: запросы копятся, нагрузка на пода растёт, автомасштабирование добавляет третью.
Чему учит. Сервис, который отвечает кодом 200 за две секунды, формально доступен и фактически бесполезен. Поэтому цель по времени ответа — такая же цель, как доступность, и следить за ней нужно по доле быстрых ответов, а не по среднему времени: среднее прячет как раз тех посетителей, которым плохо.
Час пик¶
Что делает. Переводит модельное время на 08:30 — интервал выпуска сокращается, число составов на схеме растёт примерно вдвое, поток обращений жителей усиливается.
Что видно. Больше составов в каждом кадре, дольше расчёт такта, крупнее кадры потока событий. Это не авария, а честная проверка того, как сервис ведёт себя под предметной нагрузкой. Модельное время само вернётся к настоящему через пятнадцать минут.
Наплыв запросов¶
Что делает. Поднимает цель по нагрузке для генератора: тот забирает новое задание и увеличивает частоту запросов к API.
Что видно.
- Частота запросов растёт на графике.
- Через минуту-две
HorizontalPodAutoscalerдобавляет реплику — не по загрузке процессора, а по прикладной метрике «запросов в секунду на пода». - Время ответа остаётся в пределах цели: масштабирование успевает.
Чему учит. Загрузка процессора — плохой признак для сервиса, который в основном ждёт. Масштабироваться нужно по той величине, которая описывает работу.
Вернуть в обычный режим¶
Выключает все сценарии, отпускает удержанную память, сбрасывает модельное время и цель по нагрузке. Куча после этого опадает не мгновенно — сборщику нужно несколько циклов, и на графике это тоже интересно посмотреть.
Как это устроено внутри¶
Сценарии — обычная часть приложения, а не внешний инструмент. Состояние живёт в одном компоненте на атомарных переменных, задержку добавляет обработчик запросов, рост кучи — планировщик, который раз в такт добавляет блок в список. Сами переключатели опубликованы как метрики, поэтому на любом графике видно, был ли в этот момент включён сценарий:
Такой подход стоит трёх десятков строк и не требует ни оператора, ни отдельного инструмента внедрения отказов. Для стенда это верный размер решения; в промышленной среде отказы вносят снаружи, чтобы не тащить их код в приложение.