Для того, чтобы это не было очередным рассказом, как мы всё классно автоматизировали, сразу обозначу две цели этой статьи: Я хочу представить вам наше решение как методологию или концепцию, чтобы о ней узнали и поняли что так тоже можно. Мы назвали это PerfOps. Я хочу разделить нагрузочных инженеров и PerfOps и показать вам в чем же разница. В самом начале у нас в Самокате была задача — внедрить практику нагрузочного тестирования на каждый релиз, чтобы минимизировать проблемы с производительностью на проде. А еще сделать это не потратив все деньги мира, ну и желательно внедрить это не за пятилетку. И вот где-то тут начинается немного магии. Поэтому давайте наденем поварские колпаки, возьмем котел и попробуем приготовить PerfOps-инженера который должен нас спасти. Меня зовут Кирилл Юрков, я SRE-тимлид Samokat.tech. Сегодня поговорим про нагрузочное тестирование. Про то, как мы решали обозначенную проблему, какие грабли нам попались, и какие трудности удалось преодолеть. Мне кажется, чтобы во всем разобраться, лучше всего рассказывать про свой опыт. Самокат, как мы любим говорить — это оффлайновый CDN, только не для доставки пакетов, а для доставки товаров. Когда я пришел, там был табун аутсорсеров, который делал страшные перформанс-тесты, забюрократизированная документация и странный мониторинг. Казалось, это можно быстро причесать и все будет летать! Но на деле, оказалось не так просто. Рос трафик, количество продуктов, сложность технологий, и это не подразумевало долгого причесывания. К тому же, на старте я был единственным нагрузочным инженером. Поэтому, чтобы внедрить классное нагрузочное тестирование, пришлось крепко подумать. Думать начали с подходов к нагрузочному тестированию — какой выбрать? И первый подход, который, наверное, всем приходит на ум — это когда выделяют функциональные команды, туда добавляют менеджера, разработчика и само собой «нагружатора», я это называю продуктовый подход. Мы решили подумать, насколько эффективен такой вариант в нашем сценарии и сделали модель: Предположим, у нас есть 6 основных команд и еще сколько-то будут постоянно появляться — мы же растем. Внутри каждой есть сколько-то нагрузочных инженеров. Так или иначе они достаточно обособлены. Цветами обозначен их уровень эффективности: Зеленые классно находят все перформанс проблемы, прямо детективы.  Желтые сколько-то находят, сколько-то не находят, но в целом какой-то value дают.  Красные — это разгильдяи, которые на работе играют в Counter-Strike и ничего не находят. Мы их не любим, но тем не менее они есть. Этот же цвет, скорее всего, будет отражать и качество проведения тестов. Для наглядности мы решили поставить каждой команде оценки эффективности по 10-балльной шкале. Насколько такие сотрудники могут обеспечить качество своего продукта исходя из своего скилла, подходов и прочего. Они условные, так как на проекте может и не быть перформанс-проблем. Допустим, получился итоговый балл за перформанс-качество по всей нашей технологической системе в целом 5,3. Есть слагаемое X, в эту величину попадут все остальные команды, которые есть или появятся в будущем. Поэтому итоговый балл очень нестабильный, зависит от большого количества факторов и непонятно, как на него влиять. Помимо этого, мы посчитали сколько это стоит.  Мы платим условные доллары каждому инженеру за его эффективность. У нас получается какой-то бесконечный прайс, который зависит от количества наших продуктов и будет линейно расти. Насколько — тоже непонятно. Если мы платим столько денег, то, может быть, можем улучшить балл за общее качество нашей технологической системы с точки зрения перформанса? Давайте попробуем его повысить. Например, проведем митапы. Ведь у нас есть крутые эффективные перформанс-инженеры в зеленых командах, которые сидят и ждут: «Возьмите наши знания, мы готовы делиться!» Мы провели митапы. Участники посмотрели: «Ага, у нас свой велосипед, у вас свой, почему мы должны что-то переделывать? И вообще, наверное, надо завести базу знаний», но ее нужно поддерживать. Переиспользование знаний — это очень сложно в таком подходе. Откуда взять ресурсы опять-таки непонятно. В общем, все тяжело поднимается, особо не едет. Кто-то на полбалла за счет митапов улучшил свою оценку за качество, но в общем зачете это практически не отражается, и средний балл все также нестабилен. Может быть, нужно провести полноценное обучение? Научить всех быть супер-спецами. Они будут делать красное нагрузочное тестирование, и все запоет-засияет. Обучили какой-то состав, ребята стали супер-спецами… и ушли в другую компанию, потому что там больше платят, например. Или заскейлили команды в 2 раза, пришли другие перформанс-инженеры — и что, их опять обучать? Значит, они будут приносить пользу на проекте сильно позже. А если не обучать, может быть, тогда сразу во все продукты нанять  суперспециалистов, рок-звезд в нагрузочном тестировании, и они все сделают прекрасно? Я вас заранее разочарую — этот вариант невозможен даже для компаний с бесконечным бюджетом, рынок классных перформанс-инженеров полупустой. Их просто столько нет, основная масса уже где-то сидит, и очень довольна своей зарплатой. Так мы поняли, что продуктовый подход — это очень дорогая и, потенциально, низкопрофитная история. Но что можно сделать? Альтернатива, вроде, очевидна: давайте набирать не много людей, а много знаний. Мы можем взять тех эффективных инженеров, которые сидят в зеленых командах и собрать их вместе, в одну сервисную инсорс-команду, которая будет обслуживать наши продуктовые команды и предоставлять нагрузку как сервис. Так знания о перформансе будут консолидированы в одном месте, так их можно переиспользовать и практики с подходами сделать единообразными. Тогда сервисные инженеры будут везде  делать классное нагрузочное тестирование. В Самокате мы начали ровно с такого подхода — мы последовательно внедрялись в разные команды, создавали  перформанс-тесты, и что-то автоматизировали. У нас было немного автоматизации, и все тесты мы проводили самостоятельно, одной небольшой командой. Но с очень быстрым ростом Самоката становилось все сложнее. Мы поняли, что у этого подхода тоже много подводных камней. Первый и самый основной — это контекст по продукту, который у нас отсутствовал. Было непонятно, когда в продуктовых командах релиз, когда выходит фича или вообще появился новый метод, а мы его не покрыли тестами. Как об этом узнать? А даже если узнали, то потеряли качество на покрытии или на времени погружения в контексты. Значит, надо вводить бюрократические процессы, ставить сложные ТЗ. А это сильно замедляет работу. И, естественно, возникает вопрос: «А дешевле ли это?» В моменте, наверное, да, но на дистанции — нет. Это тоже долго, просто деньги распределяются по времени. Инженеры внутри такой сервисной перформанс команды делают то же самое, что делали инженеры внутри продуктовых команд, только в качестве сервиса. А значит и ресурс примерно тот же. Разница конечно есть. Как минимум в том, что они делали кнопочные решения, чтобы потом кто угодно мог перезапустить тест. И сами по себе тесты были более качественные. Но сможет ли кто угодно понять результаты этих тестов без необходимых компетенций, большой вопрос. В общем-то Performance As a Service сам по себе в поле не воин. Тогда мы подумали, что можно сделать с сервисной командой, чтобы она работала более эффективно? Посмотрели вокруг и увидели классный подход Ops, который хорошо себя зарекомендовал внутри методологий DevOps, DataOps, TestOps. Он есть практически везде. Обычно эта методология подразумевает некую автоматизацию технологических процессов. Поэтому мы решили создать команду PerfOps, которая будет предоставлять инструментарий внутрь продуктовых команд. С его помощью они сами смогут проверить свой перформанс и сделать это максимально автоматизировано — потратив минимум ресурсов. Специалисты команды PerfOps подключатся только в случае реальной необходимости. А в остальное время будут спускать самые крутые практики. Тогда у нас будут классные перформанс-тесты и экспертиза. Нужно меньше денег, а инструментарий может разрабатывать и поддерживать меньшее количество инженеров. Контекст будет сохраняться внутри команды. Звучит многообещающе, но что же такое PerfOps? Пришла пора одевать поварские колпаки, брать котел и готовить PerfOps-инженера, который бы нам подошел. Но рецепт, честно говоря, непростой. Как выяснилось, в нашем случае, это должна быть довольно многогранная личность. Находить перформанс-баги все-таки умеют не все, потому что искать их в моменте довольно сложно. А экспертиза должна находиться в PerfOps команде, а значит основной ингредиент — это перформанс-инженер. Этой команде также нужно внедрять практики отказоустойчивости и стабильности, потому что ее основная метрика — это отсутствие перформанс-проблем на проде. Поэтому мы закинем в наш котел пару «половников» SRE. Дальше у нас есть необходимость интегрироваться с инфраструктурой. Наш инструмент должен как-то с ней жить, в ней работать и доставлять наши изменения до конечного пользователя. Поэтому надо добавить туда пару «ложечек» DevOps. Тесты должны быть в одной экосистеме и едином flow с тем, что привычно для участников продуктовых команд. Чтобы с ними могли поладить и тестеры и разработчики. Нам нужно знать, как пишутся автотесты. Поэтому нелишними здесь будут практики автотестинга — добавляем пару «чайных ложечек». Остались специи! Берем «баночку» Developer In Test. Нам же нужен единый инструментарий для создания тестов, значит его нужно либо разработать, либо взять готовый и поддерживать, а для этого нужны люди с навыками разработки. Их планировали добавить чуть-чуть, но мы слишком сильно углубились в разработку инструментария, и не сразу заметили, как отвалилась крышка с «баночки», и все специи упали в котел. Так у нас получился супер PerfOps. Он вышел из котла и пошел что-то делать. Теперь давайте рассмотрим как мы его применяем на практике, наш инструментарий и процессы внедрения. Вот так верхнеуровнево выглядит общий flow выкатки релизов в прод с точки зрения нагрузочных тестов. С помощью нашего инструментария и базы знаний продуктовая команда разработки пишет свои нагрузочные тесты и запускает их. Мы со стороны команды PerfOps предоставляем также Quality gate, который решает, пойдет релиз в прод или нет на основе результатов. Еще он подсвечивает потенциальные или явные проблемы. Если они есть — команда пробует решить их самостоятельно и пройти весь пайплайн заново. Если своими силами проблему найти не удается — подключают экспертизу PerfOps, и мы ищем ее вместе. Поэтому этот блок на стыке. Как только проблем нет, релиз катится в прод. Как мы подходили к выбору инструментария? У нас на начало внедрения новой концепции уже были тесты, написанные на Apache JMeter. У PerfOps-команды большая компетенция в этом инструменте. Вокруг него даже была автоматизация. Нам все нравилось, кроме того, что его невозможно использовать на большом количестве проектов, потому что он в Git лежит в виде страшных xml. При разработке тестов у вас  нет автокомплитов и переиспользования, а если есть, то сложные. Наш бэк разрабатывался на kotlin и логичным образом получалось, что наши команды хотят писать тесты на нем. Автотесты они запускали на junit или на чем-то похожем, для сборки использовали gradle. Мы хотели, чтобы команде было привычно пользоваться инструментарием, поэтому старались пилить его на максимально похожем стеке. Еще одним фактором были сжатые сроки. Поэтому мы оставили jmeter и рассмотрели все существующие DSL к нему, из адекватных было 3-4 штуки. В финал вышел опенсорсный проект java-jmeter-dsl. Не последнюю роль в выборе сыграла прекрасная поддержка от его разработчиков. Он был довольно сырой, но давал нам практически все что нужно для старта. Под капотом был чистенький движок. Запускался как junit тест. Можно было писать на Kotlin. По началу нам там много чего не хватало, поэтому мы начали активно развивать этот DSL, когда могли кодом, когда не могли — ишьюсами. Постепенно он начал удовлетворять все наши хотелки, а через какое-то время на нем стало в разы удобнее писать тесты. Но сами по себе нагрузочные тесты — это довольно сложная сущность, а еще сложнее её объяснить функциональным тестерам. Поэтому мы сделали еще и собственную библиотеку/фреймворк, которая упрощает их создание и дает также ряд удобных интеграций, например,  с метриками или заглушками.  Так выглядел стандартный скрипт на JMeter: Наверное, многие его видели. У него древовидная структура, все скрипты пишутся внутри UI. Это больно, сложно, но можно. Так стал выглядеть тест с помощью нашей библиотеки и DSL: Здесь есть автокомплиты, переиспользование и все необходимые плюшки. Это тот же самый тест, что был раньше, но уже в кодовом варианте. Более поддерживаемо и удобно. Данный пример на java, а не на kotlin, но IDEA позволяет конвертить его в kotlin по одному клику.  У него под капотом три компонента: JMeter-Java-DSL - исходный инструмент нагрузочного тестирования: Perf тесты как java/kotlin код; Привычный junit для запусков; Хорошая поддержка в open source; Улучшенные метрики. Performance-Factory — это обертка, которая реализует пропагандируемый нами RPS-подход в тестировании и добавляет: Автостопы; Классные метрики (интеграция Victoria-Metrics); Генерацию отчетов; Дебаггер. Gradle дает возможность: Сборки и контроля зависимостей;    Сеттинга переменных; Работы с параметрами jvm; Запуска через Gradle task. Посмотрим, как этот инструментарий лег на flow, который у нас был для доставки релизов в прод. На схеме есть слой инструментов. Первое, с чего все начинается — это merge request (мы используем GitLab). Он триггерит создание динамического стенда средствами Kubernetes, Helm и ArgoCD, который отвечает за нашу CD часть. Туда же подкидывается обфусцированный дамп, который делается средствами Airflow и заглушечный контур. Так получилась точка, куда мы можем подавать любую нагрузку. Нагрузка подается, как уже было сказано, через Apache JMeter DSL. Заглушки у нас пишутся на Mockserver, но он чуть-чуть мутированный. Еще важный момент — определить какой профиль нагрузки сейчас актуален, если хочется повторить ситуацию продакшена. Поэтому у нас есть автосборщик, интегрированный с нашей библиотекой, который внутрь теста подкидывает актуальные данные. Так можно с определенной точностью оценить, как текущий релиз жил бы на продакшене, если бы зарелизился прямо сейчас. После того, как тесты прошли, внутри merge request появляются результаты Quality Gate, то есть мы видим, какие проверки прошли, упали ли по времени или где-то есть перформанс-проблема, можно ли катиться или нельзя. Отдельно откидываются классные отчеты внутри GitLab pages, они генерируются автоматически. Если все круто — едем в прод, если плохо, кидаем на доработку и проходим весь путь заново. С момента создания PerfOps до момента, когда первая команда из 2-4 человек начала использовать этот инструмент, прошло 4,5 месяца. Нужно отметить, что все штуки, про которые я рассказал, мы старались сделать самостоятельно — не зря же в котле себя готовили. Поэтому погружались во все практики. Безусловно, нам помогали разработчики и девопсы, но мы пытались это минимизировать, чтобы самим участвовать в поддержке практик и делать это быстро и качественно. Мы действительно заморозили все другие работы на время внедрения, и уже через 2 месяца могли полноценно пользоваться этим инструментом самостоятельно и даже покрывать супер-критичные точки, которые, как нам казалось, нужно сделать в моменте. Сейчас мы находимся на этапе планового внедрения его в каждую команду Самоката и проводим микрообучения.  Не обошлось без проблем. Первая вылезла из-за инфраструктуры. Перед началом работ мы оценили, а что вообще есть. Выглядело так, что для реализации все готово! PerfOps-подход должен влететь. Были даже динамические стенды и базы — бери и запускай! Но потом оказалось, что, например, дампы не очень хотят к нам идти без обфускации. Как с этим бороться? С инфраструктурой никогда нельзя подготовиться ко всему. Я просто советую закладывать риски. Если у вас слабая бюрократия, заложите 2Х, если сильная — 4Х. Здесь может быть масса сюрпризов. И проблемы с персональными данными пользователей легко решаются. Самые сложные вопросы — концептуальные. Их было много, но ключевой в том, что если в релизном цикле присутствует нагрузочное тестирование, то страдает Time to Market. Нагрузочные тесты не делаются быстро: иногда 2 часа, а иногда 24. Это реально долго в современных релизных циклах! Поэтому мы поставили заранее несбыточную цель — успеть сделать все от нажатия кнопки «Провести тест» до разворачивания стенда и получения результатов за 15 минут. Во-первых, придумали свой кастомный тип тестов. Второе — основная проблема лежала в разрезе баз, потому что многотерабайтные базы очень долго катятся на динамические стенды, и их никак не уменьшить. Эту проблему решили наши магистры-девопсы с помощью практик черной магии на файловой системе ZFS. Также были проблемы с продуктовыми командами. Нам могли выделить 0,5 человекодня ресурсов функционального тестера, который сам не очень понимал свой сервис. Да еще у самой продуктовой команды совсем не было мотивации. Они соглашались, что это выглядит очень круто, но не все понимали зачем им это нужно. Понятно, что с каждым можно провести беседу, что-то рассказать и объяснить, но в конце концов можно все равно услышать «делать мы это конечно не будем». Решать эту ресурсно-мотивационную задачу лучше всего средствами внедрения Quality Gate. Если их надо обязательно пройти, то вопросов меньше. Все сводится к простым ответам. Зачем это делать? Чтобы пойти в продакшен! Где искать ресурсы? Где угодно. Ведь в продакшен ехать по-прежнему надо. И последняя проблема — проблема восприятия. Теперь не я пишу тесты и не я их поддерживаю. К этому сложно привыкнуть. Пока поменять мышление, к сожалению не удалось. Эта задача в процессе. Я говорил вначале, что у этого доклада есть две цели. Познакомить вас с PerfOps, и как мне кажется, это удалось. По крайней мере, теперь вы знаете, что так тоже можно. И вторая цель —  рассказать про разницу типичного нагрузочного инженера и PerfOps. У них различается практически все: Нагрузочный инженер: Живет в продуктовой команде; Сам пишет тесты и проводит испытания; Влияет только на данный продукт; Автоматизирует локально. PerfOps инженер: Живет в сервисной команде; Предоставляет инструментарий для тестов; Влияет на всю систему; Внедряет общие практики. Различаются: среда их обитания, зоны ответственности за написание тестов и результаты, сфера влияния и глобальность внедряемых практик, работа с результатами. Кажется, что PerfOps-инженер — это некая точка роста для нагрузочного инженера, и она довольно логичная и правильная, на мой взгляд. Но такой PerfOps-инженер получился у нас, а у вас может получиться другой. В любом случае, если вы выберите эту практику, то сможете сэкономить и стать быстрее: Автоматизируйте Выносите рутину в сервис Концентрируйте экспертизу Нагружайте! :) Сервисный подход — естественно, не панацея. Для его внедрения нужно быть уверенным, что у вас хватит на это экспертизы. Даже если вы просто сделаете сервисную команду, которая внутри себя агрегирует экспертизу, такой сервисный подход может быть дешевле и принести больший value. А где-то нужно автоматизировать вообще все. Подходов много, комбинируйте их и нагружайте! Приглашаем вас на Saint HighLoad++ 22 и 23 сентября в Санкт-Петербурге, где продолжим обсуждать точки роста инженеров и многое другое. Подробности, расписание и билеты ищите по ссылке.  SRE/Performance team lead