Нагрузочное тестирование ПО

среда, 27 мая 2009 г.

Мониторинг аппаратных серверов

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

Итак, какие метрики являются самыми распространенными и какие значения они могут принимать.

ЦПУ
1. Счетчики для загрузки ЦПУ
MS Performance : Processor\% Processor Time, Processor\% User Time, Processor\% Idle Time
Unix (Solaris) : sar -u : %usr, %sys, %wio, %idle
2. Значение очереди
MS Performance : System\Processor Queue Length
Unix (Solaris) : sar -q : размер средней очереди

В качестве примеров используются утилиты мониторинга MS Performance для MS Windows и sar (system activity reporter), который есть во многих unix-ах. Для Microsoft %Processor Time является метрикой используемости ЦПУ в течение контролируемого интервала. В это значение, насколько я понимаю, входит вся активность и справедливо следующее утверждение : %Processor Time + %Idle Time = 100%. Счетчик %User Time включает в себя активность прикладных программ. Для sar полная активность по использованию ЦПУ определяется суммой %usr + %sys. При этом %usr это активность прикладных программ а %sys обслуживание различных системных вызовов. Счетчик %wio показывает сколько времени (в %) было потрачено на ожидания ввода вывода. Идеально это %wio не должно постоянно быть большим и вобщем-то стремиться к нулю. Замеренные значения загрузки ЦПУ целесообразно рассматривать совместно со значениями счетчиков очереди. Очередь показывает, какое количество задач (тредов) ожидает своего выполнения. Как правило очередь появляется при увеличении загрузки ЦПУ до значений 60 и более процентов. Желательно чтобы значение очереди не превышало количество процессоров на сервере, так как в этом случае задания будут ждать и не выполняться. При этом высокая загрузка до 90% и наличие очередей допустимо, если времена выполнения операций удовлетворяют примлемым для бизнеса критериям. Надо только понимать, что этом случае у системы практически нет запаса ресурса и повышение нагрузки может привести к ухуджению (причем даже к нелинейному) производительности системы.

Память
1. Счетчики доступного объема памяти
MS Performance : Memory\Available Mbytes
Unix (Solaris) : sar -r

Если количество доступной памяти (во время теста или при эксплуатации) снизилось до 10% процентов от общего объема, то это уже повод для нахождения причин приводящих к такой ситуации. Если доступной памяти остается меньше 5%, то скорее всего нехватка памяти уже приобретает статус "узкого места". Также тенденция уменьшения размера доступной памяти в пределах значения 10 Мб/час может указывать на "утечку памяти".

Дисковые массивы.
MS Performance : Physical Disk\Avg. Disk sec/Write, Physical Disk\Avg. Disk sec/Read

Показателями медленной работы дисковой подсистемы являются значения счетчиков Avg. Disk sec/Read, Avg. Disk sec/Write идеально эти значения должны быть в пределах 10ms (для журналов транзакций СУБД в идеале 0 мсек), превышения значений счетчиков > 25ms в течение длительного времени (более 5 минут) является указателем на медленную работу дисков. Ранее вторым критерием было наличие очереди на диски, считалось, что значение 2 на шпиндель уже является проблемой. Сейчас в современных дисковых массивах, в связи с виртуализацией дискового пространства, измерение этого параметра стало затруднительным (для примитивных дисковых хранилищ типа Direct attach storage - DAS и внутренних дисков сервера этот параметр по-прежнему может использоваться). При этом, чтобы понять насколько производительно используется дисковый массив под управлением той или иной операционной системы (Unix), желательно проконсультироваться со специалистами по данному типу дискового массива.

Тестирование

Итак, сейчас добавим немного методологии по проведению самого нагрузочного тестирования. Допустим, что все предыдущие шаги успешно завершены, а это значит, что у нас есть:
1. Разработанная и согласованная модель нагрузки. Для модели отобраны критичные для данного вида тестирования операции, определены интенсивности их выполнения в тесте. Определены профили нагрузки, если Приложение имееет различные модели поведения. Рассчитаны нагрузочные точки.
2. Для моделируемых операций разработаны нагрузочные скрипты и созданы необходимые датапулы.
3. Разработаны сценарии, выполнения криптов, которые соответствуют профилям модели нагрузки.
4. Произведена проверка работы скриптов в сценариях. Необходимо исполнить каждый скрипт входящий в сценарий, используя хотя бы несколько виртуальных пользователей в группе, чтобы исключить ошибки взаимного влияния скриптов друг на друга. Тут же могут быть обнаружены скрипты с недостаточно хорошо сделанной корреляцией.

Если ошибок нет, то тогда можно приступать к испытаниям. Необходимо заметить, что оборудование тестового стенда должно в идеале как можно ближе соответствовать промышленной конфигурации. Особенно в случае, когда на основе полученных в результате тестирования времен выполнения операций будут приниматься какие-то бизнес решения. В случае если речь идет просто об оптимизации Приложения, то соответствие конфигураций тестового стенда и промышленного уже не так актуально. Для мониторинга тестовых серверов необходимо иметь доступ на сервера с правами для использования таких утилит как MS Windows Performance для MS Windows или sar, iostat, vmstat для unix-образных OS. При сохранении журналов мониторинга на тестовых серверах необходимо убедиться в наличии дискового простанства для хранения соответствующих объемов информации.

Первые запуски тестов являются пробными и позволяют понять поведение системы в целом, включая работу тестируемого Приложения и оборудования, на котором оно размещено. Начинать испытания надо с нагрузочных точек с меньшей нагрузкой, двигаясь по мере нарастания нагрузки от меньшей к большей. Может получиться так, что в процессе тестирования количество нагрузочных точек поменяется, а также изменятся количества виртуальных пользователей входящих в ту или иную нагрузочную точку. Хотелось бы так же заметить, что результаты испытаний в идеале должны быть логически согласованы. Это значит, что при увеличении нагрузки, результаты времен выполнения операций (и загрузки тестового оборудования) должны соответственно ухудшаться, а не наоборот. Если на нагрузочной точке с большей нагрузкой результаты лучше, то такой эксперимент надо перепровести, чтобы понять причины такого "выброса". Как вариант возможна ситуация, что нагрузочные точки были неправильно спроектированы и возможно нужно увеличть размер "шага", чтобы действительно почувствовать увеличение нагрузки. В заключение хочется добавить, что набор экспериментов (и как следствие результатов) должен быть достаточен для того, чтобы можно было провести анализ "узких" мест и сделать выводы о производительности и стабильности работы тестируемого Приложения.

вторник, 10 февраля 2009 г.

Доступ к объектам формы

Web Click&Script : HP Load Runner

В отдельных случаях не остается ничего кроме как работать с объектами формы непосредственно с помощью javascript-а, используя их методы и свойства. Технология Web (Click and Script) предоставляет такую возможность. С точки зрения DOM (Document Object Model) любой объект на веб странице должен иметь свой уникальный идентификатор. Выяснив этот идентификатор любым путем, например, анализируя source code для той или иной страницы, впоследствии можно писать операторы вручную, взяв в качестве образца какой либо похожий по типу объект формы. При этом такие элементы DESCRIPTION как name или type уже становятся второстепенными. Выполнение этого оператора будет в основном зависеть от того что находится в ACTION.

web_edit_field("1_1",
"Snapshot=t21115.inf",
DESCRIPTION,
"Type=password",
"name= PinCode ",
"WindowType=Modal",
ACTION,
"EvalJavaScript=document.getElementById(\"CardNum\").value=\"1111222233334444\"",
LAST);

web_edit_field("1_2",
"Snapshot=t21116.inf",
DESCRIPTION,
"Type=password",
"name= PinCode",
"WindowType=Modal",
ACTION,
"EvalJavaScript=document.getElementById(\"CardOwner\").value=\"Shirobokov\"",
LAST);

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

Работа с модальным окном

Web Click&Script : HP Load Runner

При работе с модальными окнами в технологии Web Click and Script может не происходить запись трафика для операций, выполняемых в самом модальном окне. Напомним, что под модальным окном понимается всплывающее диалоговое окно, вызываемое методом ShowModalDialog в javascript-e. Технологией, по которой сделано Приложение, использующееся в качестве примера, является ASP.Net, это значит, что в данное модальное окно загружается динамически сформированная на сервере форма (технология Active Server Page). Фактически запись трафика прекращается после отработки оператора, вызывающего модальное окно. В нашем случае это:

web_text_link("Запросить баланс из банка",
"Snapshot=t91.inf",
DESCRIPTION,
"Text= Запросить баланс из банка ",
ACTION,
"UserAction=Click",
LAST);

Предлагаемое решение заключается в регистрации, так называемой call back функции, в которую и включаются Click and Script операторы обработки полей и кнопок формы, расположенной в модальном окне. Регистрация call back функции происходит с использованием оператора web_reg_dialog, применить который необходимо перед использованием оператора непосредственно вызывающего модальное окно. Вот так:


web_reg_dialog(
DESCRIPTION,
"Type=Modal",
ACTION,
"SetCallback=ModalDialog1",
LAST);

web_text_link("Запросить баланс из банка",
"Snapshot=t91.inf",
DESCRIPTION,
"Text= Запросить баланс из банка",
ACTION,
"UserAction=Click",
LAST);

А теперь пример обработки полей и кнопок внутри call back функции. Реализовано в виде добавленного в скрипт файла с именем МodalDialog1.c и одной функцией ModalDialog1(). Разумеется, что кусок кода в файл ModalDialog1 приходится добавлять вручную, зная идентификаторы или имена объектов находящихся на форме внутри модального окна.

ModalDialog1()
{
...
web_edit_field("pin code",
"Snapshot=t21117.inf",
DESCRIPTION,
"Type=password",
"name=PinCode",
"WindowType=Modal",
ACTION,
"SetValue=хххх",
LAST);

web_button("btnSubmitModalDialog",
"Snapshot=t21118.inf",
DESCRIPTION,
"Type=submit",
"WindowType=Modal",
"name=btnSubmit",
LAST);
...
Return 0;
}

Кнопка с названием “btnSubmit” выполняет submit формы модального окна.

Остается добавить, что в этом случае необходимо присутствие в скрипте (*.h) файла (modal_dialog_callbacks.h) с определениями.

#ifndef _MODALDIALOGCALLBACKS_H
#define _MODALDIALOGCALLBACKS_H
#include "ModalDialog1.c"
#endif // _MODALDIALOGCALLBACKS_H

Файл globals.h также должен учитывать внесенные в скрипт изменения.

#ifndef _GLOBALS_H
#define _GLOBALS_H
//-----------------------------------------------------
// Include Files
#include "lrun.h"
#include "web_api.h"
#include "lrw_custom_body.h"
#include "modal_dialog_callbacks.h"
//-----------------------------------------------------
// Global Variables
#endif // _GLOBALS_H

Еще раз замечу, что при использовании операторов, выполняющих операции в модальном окне необходимо указывать тип окна – модальное (“WindowType=Modal”).

Протокол Web (Click and Script) : HP Load Runner

Начиная с версии 8.1, в Load Runner-e появилась альтернатива использованию протокола web (http/html) при работе с Web приложениями. Такой технологией является протокол Web (Click and Script). При просмотре записанного трафика вначале довольно непривычно не видеть знакомых web_submit_form или web_url, соответствующих точной последовательности обменов данными между клиентом и сервером. Вместо них появляются web_link, web_button, web_browser и так далее. Протокол Web (Click and Script) помещает в файл скрипта операторы, соответствующие использованию объектов пользовательского интерфейса. Последовательность операторов в скрипте соответствует последовательности использования тех или иных объектов (GUI) пользовательского интерфейса. При работе с Web (Click and Script) отпадает необходимость в применении ряда корреляций особенно связанных с сессионными и другими специальными идентификаторами, передаваемыми от сервера к клиенту и обратно. Например, можно забыть о кошмаре корреляции огромных VIEWSTATE-ов при работе с ASP.NET или о корреляции разнообразных cookies и так далее. При работе с Web (Click and Script) Load Runner эмулирует собой Web browser и таким образом берет эти функции на себя. Разумеется, что корреляция, связанная с работой самого Приложения, если таковая необходима, не может быть выполнена Load Runner-ом автоматически. Так что совсем избежать изучения журналов выполнения скриптов может не получится, тем не менее применение технологии Web (Click and Script) во многих случаях позволяло экономить силы и время.

вторник, 9 декабря 2008 г.

Программирование динамического оператора

Описываемая техника применялась в работе с Web (http/html) протоколом в HP Load Runner.

Иногда может быть полезным не добавлять параметры в датапулы, увеличивая их количество и усложняя структуру, а генерировать данные внутри скрипта, меняя их от итерации к итерации. При этом необходимая часть оператора строится динамически в виде строки, в которую каждый раз вставляются обновленные данные. В примере, динамически меняющимися на каждой итерации данными, являются даты начала и конца периода (переменные day_start и day_stop меняются каждую итерацию), используемые для построения отчета. Пример приведен в качестве иллюстрации динамического конструирования операторов и перебирает дни в диапазоне только от 1 до 30.
Сконструированными частями оператора будут строковые переменные url и referer. Обе они включаются в состав оператора web_url.

Action()
{

static int dstart = 1, dstop = 1;
int i,j;
char tr_name[50],
url[512],
referer[512],
param[512],
host_name[128],
day_start[4],day_stop[4];
...

strcpy(host_name,lr_eval_string("{host}"));
itoa(dstart,day_start,10);
itoa(dstop,day_stop,10);

lr_message(host_name);
lr_message(" %s %s", day_start, day_stop);

....

strcpy(url,"URL=");
strcpy(referer,"Referer=");
strcpy(param,"https://");
strcat(param,host_name);
strcat(param,"/site/transactions/TransactionsReport?sortBy=0&sortName=fine&sortOrder=A");

lr_output_message(param);

strcat(param,"&dayFrom=");
strcat(param,day_start);
strcat(param,"&monthFrom=8&yearFrom=2005&dayTo=");
strcat(param,day_stop);
strcat(param,"&monthTo=1&yearTo=2006&dateType=delta&Status=S");

lr_output_message(param);

strcat(url,param);
strcat(referer,param);

lr_message(url);
lr_message(referer);

lr_start_transaction("Search transactions");

web_url("TransactionsReport",
url,
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t3.inf",
"Mode=HTML",
EXTRARES,
"Url=/site/images/big_s.gif", referer, ENDITEM,
"Url=/site/images/link_list_head.gif", referer, ENDITEM,
LAST);

lr_end_transaction("Search transactions", LR_AUTO);

dstart++;
dstop++;
if (dstart == 31)
{
dstart = 1;
dstop = 1;
}
....
return 0;
}

Практические аспекты нагрузочного тестирования

Начиная с этой статьи, будут публиковаться материалы по практическим вопросам нагрузочного тестирования. В основном это интересные с моей точки зрения решения тех или иных проблем, встреченных при работе над проектами. Подготовка к тестированию - это, как правило, разработка тестовых скриптов и сценариев. Поэтому первые статьи будут посвящены разработке скриптов с помощью инструмента нагрузочного тестирования HP Load Runner. Возможно что то из моего опыта пригодится кому то еще. При этом не вижу большого смысла «перепечатывать» главы из документации или из книг выпущенных компаниями HP (Mercury), так как каждый может ознакомиться с ними самостоятельно. Также уверен, что большинство проблем можно решать на основе стандартной документации и решений предлагаемых HP (Mercury), что и сам почти всегда стараюсь делать. Пока буду включать в блог все статьи, посвященные практике подряд, по мере их появления. Возможно это приведет к некоторой потере логической стройности, которой я старался придерживаться до сих пор. Впрочем блог это не книга, так что надеюсь на понимание:).