Как сделать инструмент для запуска нагрузки одной кнопкой: показываем наш Pangoloader

от автора

Привет, Хабр! Меня зовут Дмитрий Королёв, я инженер по нагрузочному тестированию Platform V Pangolin — целевой СУБД в Сбере и не только. Эту статью я написал вместе с моим коллегой Алексеем Хорохориным @AlexeyHorohorin. Наш продукт — специальная сборка PostgreSQL с доработками (крупных больше 30, а всего уже больше 70) в области безопасности, производительности, отказоустойчивости.

Условия для нас таковы: мы тестируем продукт целиком, в разных версиях, на разных ядрах. У нас работает три версии в параллель для восьми разных ОС, и тестировать нам нужно при использовании и неиспользовании разных фич. А теперь представьте, сколько тут интеграций…

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

Как устроено нагрузочное тестирование очередного релиза Pangolin

Сначала тестируем максимум TPS (транзакции в секунду), подтверждаем его двухчасовым тестом. В тестировании максимума есть ступеньки: поднимаем нагрузку до стабильной ступеньки и гоняем два часа, чтобы убедиться в том, что это точно максимум. Потом 24-часово тест стабильности: смотрим утечки памяти и прочие проблемы, которые могут произойти. После него тест отказоустойчивости (failover). Если отказывает мастер (выходит из строя), то проверяем, насколько успешно и как долго происходит его смена, как реплика становится мастером (реплика — это как запасной парашют).

Раньше мы делали нагрузку самописными скриптами на Bash. Это простой и доступный способ, но он не позволял нам реализовать универсальный механизм для одновременного запуска множества сценариев тестирования. Что ещё важнее, с ним сложно сформировать итоговый отчёт по завершении тестирования. А собирать такой отчёт вручную долго, и ещё нужно не забыть включить всю информацию…

Поэтому в конце 2022 года у нас появился свой инструмент для нагрузки.

Что представляет из себя наш Pangoloader

Это связка из двух инструментов:

  • Benchbase — open source-инструмент для проведения нагрузочных тестов для различных СУБД. Его мы доработали под наши требования. 

  • Pangoloader — инструмент на Python. Он позволяет подготавливать и запускать нагрузочные инструменты, такие как Benchbase, отслеживать их статус работы и собирать нам красивый итоговый отчёт на HTML-странице, куда выгружаются настройки СУБД, флаги сборки, графики за время тестирования, бизнес-метрики и системные метрики.

Эта статья посвящена Pangoloader, но здесь коротко ответим на возможные вопросы про Benchbase и выбор первого решения в связке.

Какие еще инструменты можно было использовать:

  • Pgbench содержит базовый сценарий нагрузки, но нам хотелось чего-то посложнее. К тому же pgbench — это встроенный бенчмарк для тестирования PostgreSQL, не получилось бы сравнить производительность на одном сценарии на разных СУБД/

  • Jmeter — у нас не было опыта работы с ним, а всю логику нагрузочного сценария и генерирования данных для него пришлось бы реализовывать на нём, что заняло бы довольно много времени.

  • HammerDB может нагружать различные СУБД для сравнения производительности, но у него всего два сценария нагрузки. 

Выбрали Benchbase, потому что:

  • он может нагрузить разные СУБД;

  • у него много подготовленных сценариев;

  • реализован на Java, у нас в ней есть опыт, можно внести свои доработки;

  • готовая база для создания своих сценариев нагрузки.

Вернёмся к Pangoloader. Вот как всё устроено. Перед запуском утилиты готовим файл конфигурации в формате YAML:

stand:  stand_1:    ssh_user: pprb_dev    host: 65.32.1.29    postgresql:      port: 5433    pgbouncer:      port: 6544  benchmark:  benchbase:    host: 65.32.1.30    config: /tmp/tpcc_config.xml    command: java -jar /home/pprb_dev/benchbase-postgres/benchbase.jar    scalefactor: 2500    terminals: 250    time_load: 300    rate_load: 100    test_port: 6544

Прописываем серверы, на которых расположен тестовый стенд с СУБД, и хост с утилитой нагрузки:

ssh_user:  pprb_dev:    name: pprb_dev    password: pprb_dev_pass  postgres:    name: postgres    password: postgres_pass sql_role:  postgres:    name: postgres    password: P@ssword  pangoloader:    name: postgres    password: P@ssword  pgbouncer:    name: pgbouncer    password: pgbpass

Вот секция для определения SSH- и SQL-пользователей. Они участвуют в тестировании:

grafana:  host: 65.32.1.5  port: 3000  api_key: eyJrIjoiTTVhTHpSd...  render_params:    theme: light    width: 1280    height: 720    var-interval: 2s  render_processes: 4  prometheus:  host: 65.32.1.4  port: 9090

Потом указываем хосты для утилит мониторинга Grafana и Prometheus. Выбираем некоторые параметры для рендера картинок с графиками, которые потом попадают в итоговый отчёт.

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

Сценарий нагрузки выглядит так:

class tpcc_load(Scenario):     dbname = 'First_db'    time = 7200    rate = 1260    test_port = 'pgbouncer'    test_generate_report = True     Scenario.description = """Тест подтверждения максимальной нагрузки.    Тест проводится на ступени нагрузки, предшествующей L0 (или на уровне нагрузки 90% от L0). Длительность стабильной нагрузки не менее 1 часа."""

Это класс, который представляет из себя сценарий тестирования. Здесь объявляются нужные в этом тесте параметры. Например:

  • dbname — имя тестовой базы данных в СУБД;

  • time — время нагрузки;

  • rate — интенсивность нагрузки;

  • test_port определяет, к какому порту будут подключаться тестовые клиенты;

  • test_generate_report определяет, нужно ли генерировать отчёт по завершении сценария тестирования;

  • Scenario.description — текстовое описание сценария и того, что в нём происходит. Потом это описание попадает в отчёт.

Класс наследуется от класса Scenario. Это абстрактный базовый класс, в нём содержится три метода:

  • setup — служит, например, для предварительной настройки тестируемого объекта. Установка корректных параметров, перезапуск базы, генерация тестовых данных и так далее.

  • execute — сам сценарий теста. Здесь запускается нагрузка, с которой нам надо получить результаты в виде итоговой производительности, метрик системных ресурсов и прочего. Отчёт будет содержать данные только в интервале работы этого метода.

  • teardown — выполняется по завершении нагрузки. Он восстанавливает параметры до исходных значений, чтобы вернуть тестируемый объект в исходное состояние.

Так выглядит метод execute для примера:

def execute(self):        benchmark = utils.Benchmark()        scalefactor = benchmark.scalefactor        terminals = benchmark.terminals              if tpcc_load.test_port == 'postgres':            conn_string = ','.join(f'{pg.get_host()}:{pg.get_port()}' for pg in config.postgresql_list())        elif tpcc_load.test_port == 'pgbouncer':            conn_string = ','.join(f'{pg.get_host()}:{pg.get_port()}' for pg in config.pgbouncer_list())         bench_cfg = benchmark.read_config('/home/pprb_dev/benchbase-postgres/config/postgres/tpcc_load.xml')        bench_cfg.find('url').text = f'jdbc:postgresql://{conn_string}/{tpcc_load.dbname}?ApplicationName=tpcc&reWriteBatchedInserts=true&prepareThreshold=0&targetServerType=primary'        bench_cfg.find('username').text = config.SQLRole('pangoloader').name        bench_cfg.find('password').text = config.SQLRole('pangoloader').password        bench_cfg.find('scalefactor').text = f'{scalefactor}'        bench_cfg.find('loaderThreads').text = f'{tpcc_load.loaderThreads}'        bench_cfg.find('terminals').text = f'{terminals}'        bench_cfg.find('works').find('work').find('time').text = f'{tpcc_load.time}'        bench_cfg.find('works').find('work').find('rate').text = f'{tpcc_load.rate}'        bench_cfg.find('works').find('work').find('weights').text = f'{tpcc_load.weights}'        benchmark.write_config('/tmp/tpcc_config.xml', bench_cfg)        benchmark.run(                "--bench tpcc",                "--config /tmp/tpcc_config.xml",                "--create=false",                "--clear=false",                "--load=false",                "--execute=true",                with_log = True,                )

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

pangoloader --config config.yaml --report-template template/base.j2 --log-file pangoloader.log tests.tpcc_load

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

Что получилось в итоге

Pangoloader заметно упростил нам работу. Теперь мы можем:

  • запускать нагрузку одной кнопкой;

  • настраивать мониторинг на ВМках;

  • менять конфигурацию окружения, где тестируем, конфигурацию сценариев;

  • запускать несколько сценариев подряд;

  • собирать результаты по каждому виду теста и формировать подробные и удобные отчёты.

Мы продумывали наполнение итогового отчёта, чтобы потом в любой момент можно было повторить тот же тестовый сценарий и проанализировать результаты теста целиком.

Итоговый отчёт

Итоговый отчёт

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

Ниже — информация по сценарию нагрузки: какой тестовый сценарий был запущен, с какими параметрами. Схема тестовой базы данных, размер таблиц и количество записей в них, размеры индексов для таблиц.

И вот информация с результатами в виде графиков мониторинга — тут представлены графики системных метрик (CPU, RAM, disk), статистика интенсивности нагрузки (TPS, latency). Вся эта подробная информация скрыта под ссылками и открывается на отдельных страницах.

Планы: что хотим добавить в наш нагрузчик

Собираемся и дальше развивать Pangoloader. Самая интересная и сложная фича, которую хотелось бы добавить, — автоматизированный анализ отчётов. Было бы здорово, если бы при открытии отчёта проблемные места автоматически подсвечивались красным цветом вверху страницы. Этого можно достичь, например, сравнив показатели с эталонными значениями и выделив несоответствия. Или сравнив результаты с предыдущими тестами. Но пока это лишь размышления, мы ещё не проверяли идею на практике. Начнём пробовать — будем понемногу рассказывать об этом в сообществе нашей команды, присоединяйтесь, если интересно.

А если у вас есть такой опыт в автоматизации нагрузки, будем благодарны за комментарии. Спасибо за внимание!


ссылка на оригинал статьи https://habr.com/ru/articles/847334/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *