Боевые стрельбы в ночи, или Почему нагружать прод — не страшно

cout8grxjcpmjaxmehfjzozvy54.gif
«А если ты не выстрелишь, то испорчусь я»

Ещё недавно считалось, сервис должен просто работать. Нарисовали, заверстали, написали скрипты — вроде всё ок, можно катить на прод.

Но конкуренты не дремлют, поэтому начинается гонка не только за новыми функциями, но и за скоростью работы. Любое зависание приложения или долгий ответ сервера (не говоря уже про всплывающие 500-е ошибки) портят впечатление от сервиса и вынуждают пользователя уходить куда-то ещё. Наверняка, каждый сталкивался с ситуациями, когда вместо покупки билета на самолет, поезд или концерт на экране отображалось «Internal server error», и вы в ярости хотели разбить монитор.

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

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


Зачем её исследовать?

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

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

В-третьих, опираясь на актуальные данные о производительности, бизнесу легче планировать развитие сервиса и выбирать направления роста.

У тех, кто впервые озадачился такой проблемой, возникает вопрос: где и как измерять производительность? Зачастую для подобных экспериментов используют стенд. В отдельных компаниях существует специальный стенд для исследований производительности. Если он у вас есть — отлично! Если он 1 в 1 соответствует проду, то у вас всё замечательно. Но чаще всего содержать стенд, полностью соответствующий проду, очень дорого. Как же быть? Выходит, единственное место, полностью соответствующее проду, — это сам прод?

Для многих предложение что-то измерять и проверять прямо на проде звучит еретически. Не пугайтесь, если всё делать аккуратно, ничего плохого не случится. Мы, например, заранее просчитываем возможные риски и определяем, что в нашей системе может пострадать от эксперимента. Вместе с этим планируем, как снизить опасность, и постоянно мониторим состояние системы.

Исследования на проде не отменяют использование стенда. На нем можно проводить проверки релизов и специальные эксперименты по изучению производительности микросервисов, включая их по отдельности или в различных сочетаниях.

Главное и неоспоримое преимущество результатов, полученных на проде, — они самые честные из всех вариантов и максимально похожи на реальную обработку пользовательского трафика. Как бы ни приближался стенд к проду по характеристикам — догнать его, как и Ахиллес черепаху, он не сможет. При исследованиях на проде вы будете использовать те же БД, что и реальные юзеры, ту же сеть, то же окружение. Не надо ничего строить, всё уже построено до вас и исправно функционирует.

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


Выбор сценария и схемы подачи нагрузки

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


Выбор сценария

Первый шаг, самый главный, выбрать исследуемые сценарии. Это могут быть как одиночные запросы (например, проверка баланса), так и сценарии со сложной логикой, где каждый следующий запрос зависит от результатов предыдущего (оплата товара в магазине, перевод с кошелька на кошелек). Мы регулярно берём список всех бизнес-процессов, которые существуют в системе. У нас таких процессов больше 400. Исходя из целей бизнеса, мы согласуем приоритеты сценариев.

Какие сценарии отнести в группу приоритетных?


  • Те, по которым ожидается всплеск пользовательской активности в ближайшем будущем.
  • Те, по которым есть постоянные жесткие ограничения (по разным причинам), которые не позволяют опускаться ниже SLA.

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

Набор методик и инструментов выбирается в зависимости от логики сценария. В нашем случае приоритетные сценарии имеют разветвленную логику. Например, при платежах картой проводятся различные проверки, в зависимости от которых сценарий идет по своей ветке, поэтому мы для их реализации используем JMeter. Он удобен как раз для таких сложных сценариев, где каждый следующий запрос зависит от результата предыдущего. Если нужно стрелять одиночными запросами, то рекомендую использовать высокопроизводительный Phantom.

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


Схема подачи нагрузки

На втором шаге мы выбираем схему подачи входной интенсивности.

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

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

Подача интенсивности тоже может быть разной. Остановлюсь на двух самых распространенных профилях. Это тест с линейно (или ступенчато) растущим подаваемым потоком интенсивности и stability тест, в котором проверяется длительная работа сервиса под стабильно большим потоком интенсивности. Второй вариант требует длительного времени исследования, что не всегда возможно на боевой среде, к тому же для него уже должен быть известен уровень подаваемой интенсивности.

nkv_2q_qvn7otgyh2uyz4q8jjgk.png
По оси X — время, по Y — интенсивность нагрузки (запросов в секунду)

Хорошо, когда есть определенный SLA, на основе которого можно проводить проверку, отслеживая производительность, время ответа и мониторя поведение компонентов. Чаще встречается ситуация, когда уровень производительности неизвестен и требуется его определить. Для этого используем первый вариант — замер при растущей подаваемой интенсивности. Включаем входной поток, линейно или ступенчато его увеличиваем, смотрим на поведение сервиса. Линейно подаваемой нагрузкой можно точнее отследить точку насыщения и точку разладки. Про это подробнее было рассказано в нашей статье. Зато ступенчато подаваемая интенсивность комбинирует в себе в том числе небольшие stability тесты, особенно если ступеньки продолжительны по времени. Не рекомендуется сразу подавать большой поток нагрузки на вход, лучше «прогреть» сервис, постепенно наращивая входной поток.

Ещё можно провести серию из двух экспериментов. Сначала измерить линейно подаваемой нагрузкой точку насыщения и остановиться. Не следует продолжать подавать поток дальше до разладки, это все-таки прод, а не стенд. Вторым экспериментом посмотреть на поведение сервиса под ступенчатой нагрузкой, выбрав несколько ступенек около точки насыщения. А уже дальше провести stability тест, насколько позволяет время, выбрав для него нагрузку на 15–20% ниже точки насыщения (или разладки, если у вас она вдруг случилась до насыщения). Выше забираться опасно.


Выбор времени проведения

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

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

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


Сложности при работе с контрагентами

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

И наоборот: если заменить сервис контрагента заглушкой, то подготовка к стрельбе сильно упростится, но и честность результатов снизится. Здесь следует учитывать, что заглушка должна максимально имитировать поведение контрагента, а не просто отдавать 200 ОК.

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


Проверка доступов и согласования с СБ, финотделами, админами

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

Нужно проверить наличие необходимых доступов. Убедиться, что ничего не помешает проведению исследований и, если необходимо, заказать доступы у сетевых админов, как у своих, так и у контрагентов, если вы работаете с ними. Сетевые админы помогут и с настройкой балансировки. У нас однажды балансировщик был переключен с round-robin на ip-hash. В результате все наши запросы попадали на один и тот же фронт, выбираемый по новому алгоритму балансировки.

После получения доступов нужно отладиться и проверить работу скрипта на минимальном единичном потоке.

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

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

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

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


Проведение стрельб и анализ результатов

Наконец, обсуждаем проведение стрельб с мониторингом. Определяем, куда смотреть во время экспериментов, при каких условиях останавливать, на какие датчики реагировать? Это нужно обязательно сделать «на берегу», до старта стрельбы.

Для остановки есть несколько причин.

1) По сигналу от мониторинга. В данном случае неважно, сломается ли функциональность, задействованная экспериментом, или возникнет нештатная ситуация на другом конце сервиса. Нужно остановить тесты и разобраться в причинах, потому что бесперебойная работа сервиса — один из главных приоритетов.
2) При росте сетевых или НТТР-ошибок. Это уже нештатная ситуация, требующая вмешательства.
3) Если достигли насыщения, производительность больше не растёт, но растёт время ответа. Не нужно ждать разладки и класть прод. Результат для анализа уже есть, можно смело останавливать эксперимент.

После эксперимента можно понять, что логов и результатов недостаточно и требуется повтор эксперимента с включенным debug-логированием. Это утяжелит лог и запись на диск, но теперь уровень требуемой нагрузки вам известен, а значит, вместо длительного теста можно обойтись сокращенным.


Анализ результатов

В конце остается проанализировать результаты и предоставить полученные данные заинтересованным сторонам. Начинать это делать можно уже во время экспериментов. Мы для анализа используем связки Zabbix и Elastic с Grafana и Kibana. Отслеживаем временные характеристики всех внешних и внутренних вызовов, задействованных в нашем эксперименте, следим за пулами коннекторов, очередями, мониторим БД. Для онлайн-слежения за метриками со стороны генератора трафика — яндексовый сервис Лунапарк (есть открытый аналог — overload.yandex.net).

Представление результатов будет отличаться в зависимости от того, кому они нужны. Для разработки, админов и тестировщиков нужен подробный отчёт с точными метриками, графиками, логами, стектрейсами. Для бизнеса важны результат и прогнозы развития. В таком случае лучше конкретность и акцентированность цифр и больше наглядности. Для этого можно использовать принцип светофора. Красная зона — плохо, нужно срочно оптимизировать. Желтая — мы заметили деградацию показателей, следует обратить внимание на это. Зеленый — все ОК, двигаемся дальше. Понятный и доступный вид результатов исследований поможет снять вопросы о важности и полезности измерения производительности.

Удачных исследований, и помните про безопасность пользователей!

© Habrahabr.ru