Разделы портала

Онлайн-тренинги

.
Основная концепция реализации нагрузочного тестирования (на примере Mercury LoadRunner).
29.09.2008 19:11

Панкратов Вячеслав, при активном участии консультанта проекта Дмитрия Шевченко.

Содержание: 

 

  • Схема + определение ролей
  • Действующие лица
  • Создание виртуальных пользователей (V-Users)
  • Создание сценариев

Схема + определение ролей.

  • Скрипт — записанные действия реального пользователя, которые можно воспроизводить.
  • Генератор нагрузки (машина + программа) которая умеет выполнять этот скрипт имитирует действия многих пользователей.
  • Контроллер (машина + программа) — которая управляет запуском, остановом пользователей на других машинах и получает от них репорты.
  • Монитор — часть контроллера, которая производит наблюдение за системой под тестом (под нагрузкой), то есть производит снятие показателей. В идеологии LoadRunner-а нет потребности устанавливать на машину под тестом дополнительное ПО, которое будет снимать показатели (и влиять на результат теста!).
  • Командуя с машины контроллера, запускаем скрипт виртуального пользователя паралельно много раз с разных машин.
  • На машине которая рулит процессом, собираем данные о проделанной работе.

Действующие лица.

Vuser — В-юзер, виртуальный пользователь, скрипт эмулирующий действия одного конкретного пользователя. Умеет то, чему мы его научим в процессе записи, параметризации и прочего препарирования пациента. К примеру: логиниться, вызывает действия по отношению к серверу, получает результат (дожидается его или нет) и отлогинивается. С точки зрения всей системы тестирования — это такой участник, который на старте получает сценарий, куда бежать и что делать, получает инструкции от контроллера по поводу того как бегут остальные в-юзеры (одной толпой, или более шустрые убегают вперёд, внимательно слушает что ему делать если где-то пробежать нельзя и на каких местах он должен что отрапортовать. Потом после свистка контроллера он бегает по известному сценарию (последовательность действий) и «отзванивается» на машинку, которая его запустила о результатах забега. С технической точки зрения, каждый в-юзер может быть отдельным экземпляром программы-движка, которая выполняет скрипт в-юзера (так выполняется быстрее, но и ресурсы ему) - то есть скрипты исполняются в мультредовом режиме (в документации стоит оговорка, что система должна поддерживать такой режим выполнения программ), а может быть одним из процессов программы-движка, тогда он будет делить память с другими в-юзерами, которыми рулит движок — памяти кушается больше, и скорость ниже.

  Multithreading поддерживается не для всех протоколов! Но если он доступен, то рекомендуется использовать именно его, а не процессы. Именно потому, что потребление ресурсов load generator machine (главным образом памяти) при этом значительно меньше, что позволяет на одном load generator запускать большее количество VUsers.

Vugen — генератор в-юзеров (писалка скриптов), такой умный тул, который сидит между клиентом, который дёргает приложение/сервер и самим приложением/сервером, которое находится под тестом. Во время работы пользователя, Vugen «ловит» все API вызовы, которые пользователь кидает на сервер (чтобы было потом что воспроизводить) и все ответы этого самого сервера (чтобы было потом с чем сравнивать).

Сценарий — Список В-юзеров (с именами и фамилиями), в котором задаётся сколько в-юзеров мы будем заставлять бегать, с каких машин, и какие скрипты мы их будем заставлять нам делать.

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

  Красивые графики строит не контроллер, а третий модуль LoadRunner’a, который называется Analysis. Oн на входе получает файл с результатами запуска сценария (.lrr-файл) и создает analysis session. Эту сессию можно сохранить, если есть необходимость (.lra-файл).

Генератор нагрузки (load generator/load injector) — реальные машины на которых стоит движок, который умеет выполнять скрипты в-юзеров. Подчиняется Контроллеру, по команде которого стартует в-юзер, слушает их «жалобы» и отдаёт рапорты на контроллер.

Создание в-юзеров.

Известно по каким протоколам общаются пользователь и сервер.
Самое болезненное зачастую определить, какой трафик мы будем ловить и преобразовывать в скрипт.

Известна последовательность действий, то есть бизнес-сценарий, последовательность действий с конечным результатом.

Запускаем тул на запись и кликаем нашу последовательность.
Логин и логофф части записываем в vuser_init и vuser_end части (при прогоне с различными параметрами, операции описанные в инит и енд части не проигрываются). Действия пользователя записываем в action часть, или создаём несколько actions, если по-логике выполняется более чем одно действие с осязаемым результатом.

Смотрим что получилось и проигрываем: получаем воспроизведение действий от лица одного пользователя (пока создания нагрузки нет).

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

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

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

Создание сценариев.

Определяем данные, которые в-юзеры смогут использовать в качестве параметров. Можно сказать вот тебе табличка/файлик и бери отсюда все по порядку, рандомно, только те которые ещё никто не брал, или вот из этого диапазона.

  Тут хороший момент: пересечение нагрузочного и функционального тестирования. Имеем табличку выгруженную в файлик — наши тестовые данные (к примеру id-шки кастомеров которые подставляются на вход выборке). Табличка большая. Но у нас и пользователй может быть много. Говорим каждому брать по куску, тебе от 1 до 100, тебе от 101 до 200 и так далее - получается, что за одну итерацию мы переберём столько вариантов сколько пользователей, и кол-во итераций зададим размером блока (интервалом).

Дмитрий Шевченко:

 

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

Иногда на вопрос "A какой протокол использует ваше приложение?" можно услышать в ответ "TCP/IP", что вообще говоря, тоже будет правильным, но абсолютно бесполезным с точки зрения нагрузочного тестирования. Нас не интересует транспортный уровень передачи данных, нас интересует application level protocol. Например, если есть две клиент/серверные системы, работающие с БД Oracle, но одна из них работает с БД напрямую, а вторая через middle tier, например Tuxedo, то и протоколы, используемые для записи скриптов для таких систем будут разные. В первом случае нам нужен Oracle 2-tier protocol и в скрипте мы увидим SQL запросы, идущие от клиента на сервер. Во втором случае нам нужен Tuxedo protocol и в скрипте мы увидим функции VUGen’а, которые дергают Tuxedo API.

Записывать login/logout соответственно в vuser_init/vuser_end это часть best practices, но вовсе не обязательно. Зависит от того хотите ли вы эмулировать login/logout для каждой итерации или только один раз. Создать несколько actions частей можно далеко не для всех протоколов (для HTTP можно).

Определять транзакции будем практически всегда (а иначе что мы собираемся мерить?). Параметризация — по нашему желанию. Если ее не делать, то надо помнить, что гонять кучу юзеров с одними и теми же данными можно (если тестируемое приложение позволит), но одинаковые запросы кэшируются и вы рискуете не получить реальной нагрузки на вашу систему. Если тестируем более или менее реальную систему, то скорее всего без корреляции (динамической параметризации) нам не обойтись. Классический пример — генерация уникального ID при вставке новой записи в таблицу БД. Записанный скрипт вы не сможете прогнать второй раз, если не сделаете корреляцию. Статическая параметризация здесь не поможет, потому что мы не знаем заранее какое именно ID будет сгенерировано, так как оно генерируется только в run-time.

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

Данные для скриптов определяем на этапе создания и отладки VUser’ов, то есть в VuGen’e, а не в контроллере. Можно закачивать данные непосредственно из БД (есть специальный Wizard, который поможет это сделать), если знаете необходимый SELECT.