Одного разу зустрілися JMeter і незнайомка...


Кадр з фільму «Будинок біля озера». Зустріч (www.kinopoisk.ru)

Джим ще не знав, як підійти до неї, з чого почати розмову і на якій мові його вести. Але він бачив багато, володів мовами і мав в рукаві не один козир. І будучи впевненим допомоги вірних друзів (це ми з вами) і забувши про сумніви, йшов на зустріч долі.

Нижче розповідь про те, як Джим завойовував знову і знову серце незнайомій системи. Не подумайте, що незнайомок було кілька. Вона була одна, єдина, але така різна, і від того історії будуть слідувати одна за одною.

Предысловие


Популярні варіанти надсилання запитів до невідомої системи

Використовував такі варіанти надсилання запитів до незнайомої системі:

  1. Створив проміжне веб-додаток, що вміє відправляти запити досліджуваної системи, а команди веб-додатком відправляв з допомогою компонента HTTP Request.
  2. Створив проміжний веб-сервіс, який уміє відправляти запити досліджуваної системи, а команди веб-сервісу відправляв з допомогою компонента SOAP/XML-RPC Request.
  3. Створив консольний клієнт до досліджуваної системи, викликав клієнт з JMeter, використовуючи компонент OS Process Sampler.
  4. Створив бібліотеку (API) на Java, C# для роботи з досліджуваною системою і викликав методи бібліотеки, використовуючи компонент JSR223 Sampler.
  5. Створив плагін JMeter.
Веб-додаток і HTTP Request або веб-сервіс і SOAP/XML-RPC Request
Відомо, що JMeter уміє відправляти HTTP і SOAP-запити. І для вирішення завдання інтеграції часто вибирається варіант створення веб-додатки, надсилає запити до досліджуваної системи, і приймаючого команди від JMeter за протоколом HTTP.

Приклад. Тестував wcf-сервіс, що працює по протоколу SOAP/MSBin1 поверх HTTP. JMeter не вміє працювати з протоколом SOAP/MSBin1, надіслати невеликий запит одним пакетом зможе дуже нечитаемом вигляді, а от відправити великий запит або отримати великий відповідь потоком вже не зможе.
Перше рішення було таким, використовуючи Visual Studio згенерував клієнта до досліджуваної системи (wcf-сервісу), і створив тестовий веб-сервіс, який міг за протоколом HTTP приймати команди від JMeter.

Або до досліджуваної системі може бути API Python. І для виклику Python-коду, можна створити веб-додаток на Python, яке буде приймати команди від JMeter і подавати навантаження на систему.

Веб-додаток для невеликої навантаження

Веб-додатки для створення невеликого навантаження на тестову систему. Важливо вести лог у веб-додатку.

При роботі з веб-застосунком завжди буде тимчасової лаг. Час взаємодії JMeter з проміжним веб-додатком буде ненульовим навіть при малому навантаженні. Тому час відповіді на запити досліджуваної системи потрібно вимірювати по логам проміжного веб-додатки. Час обробки запитів, що фіксується в JMeter, буде більший. Тому важливо вести два лода — лог у JMeter і лог в проміжному веб-додатку. Вміти парсити лог веб-додатки, будувати за ним статистику.

Веб-застосунок під великим навантаженням

Веб-застосунок під великим навантаженням може стати точкою відмови, якщо воно не мастшабируется.

При створенні великого навантаження нерідко доводиться запускати кілька JMeter. Створюється багато запитів, з яким проміжне веб-додаток може не впорається. Часовий лаг буде зростати. При великому завантаженні навіть логування у веб-додатку може запізнюватися, з'явиться додатковий часовий лаг при фіксуванні часу відповіді досліджуваної системи. Зобразив це на малюнку вище виділивши проміжне веб-додаток червоним, а стрілку до файлу лода пунктирною.

Також часто досліджувана система включає балансувальник навантаження і кілька серверів додатків. Якщо балансування навантаження здійснюється за ip-адресами клієнтів, то при використанні одного єдиного проміжного веб-додатки, навантаження буде подаватися тільки на один з вузлів досліджуваної системи. Інші вузли будуть простоювати. Изобралил це на малюнку вище, виділивши один з вузлів досліджуваної системи червоним.

Перед подачею велике навантаження важливо:

  • виставити вимоги і визначити максимальну продуктивність проміжного веб-додатки;
  • врахувати при тестуванні спосіб балансування на досліджуваній системі.

Для створення великого навантаження потрібно використовувати кілька JMeter і кілька проміжних веб-додатків, і навантаження розподілиться рівномірно

Якщо є кілька навантажувальних станцій і навантаження подається через проміжне веб-додаток. То зручно на кожній навантажувальної станції запускати окремий веб-сервер з веб-додатком, що подає навантаження.

Тоді навантаження буде розподілятися рівномірно, навіть якщо балансувальник досліджуваної системи використовує прив'язку клієнтів до серверів додатків за ip-адресами.

Для обробки безлічі логів і формування статистики за ним зручно використовувати бібліотеку Pandas (від Python). І писати лог веб-додатків так, щоб виходив відразу CSV-файл. Такі CSV-файли в циклі завантажувати, аналізувати і відразу будувати графіки, використовуючи MatPlotLib. Jupyther, Pandas MatPlotLib — вірні помічники при обробці логів.

Консольний додаток і OS Process Sampler
Варіант подачі навантаження через запуск додатків виправданий, якщо:
  • є готовий зручний клієнт у вигляді додатку для роботи з досліджуваної системою;
  • є готові модульні тести до досліджуваної системі і потрібно лише використовувати JMeter для запуску необхідної кількості потоків, що виконують ці тести і виміру часу їх виконання;
  • потрібно використовувати багато криптографію, ви знаєте C#/Java і вмієте працювати з криптографією на C#/Java;
  • до досліджуваної системи є SDK .NET/Win32/Java/Python і ви знаєте C#/C++/Java/Python і можете легко написати консольний клієнт за прикладами з SDK;
  • потрібно завантажувати або відправляти величезні файли і стандартні компоненти JMeter споживають занадто багато ресурсів при виконанні таких запитів;
  • при роботі з досліджуваної системою складний сценарій, який простіше реалізувати та відлагодити в IDE (Intellij IDEA, Eclipse, KDevelop, Visual Studio, ...), ніж формувати у JMeter.

Подача навантаження на тестову систему через запуск клієнтських додатків

Перший раз використовував навантаження через консольний додаток, коли в тесті треба було завантажувати файли розміром більше 100 МБайт до декількох гігабайт за протоколом HTTP. JMeter при отриманні таких відповідей споживав всю доступну оперативну пам'ять. На допомогу прийшов wget, цей консольний інструмент без праці викачує величезні файли, споживаючи мінімум ОЗУ, має налаштування дозволяють включити і вимкнути gzip keepalive. OS Process Sampler та wget дозволили прокачати канал і виконати тестування, чого не можна було досягти використовуючи HTTP Request.

Особливості використання додатків:

  • додаток це окремий процес, і він споживає багато оперативної пам'яті, для створення великого навантаження знадобиться багато ОЗУ, швидкий процесор або кілька навантажувальних станцій;
  • кожен додаток буде вести свій окремий лог, потрібно подбати, щоб безліч логів потім було зручно опрацювати і отримати за них статистику;
  • марнотратно запускати додаток для виконання лише одного короткого запиту до досліджуваної системи, зручно реалізовувати в додатку цілий сценарій: аутентифікація, кілька ітерацій корисних дій і вихід.
Додатки не стають точкою відмови. При їх роботі тимчасової лаг набагато менше, ніж при використанні проміжного веб-сервісу або веб-додатки. Їх легко розробляти і налагоджувати.

Щоб консольний додаток вміло виконувати сценарій, зручно реалізувати в ньому прийом сценарію зі стандартного входу, використовуючи свій псевдокод. Наприклад, такий:

#AuthByCertificate
"Іванов Іван Іванович"
#GetInboxDocuments
#GetContagentList
#SendDocument
".\data\Document1.txt"
#SendDocument
".\data\Document2.jpg"
#Exit

І написати парсер для такого сценарію: якщо рядок починається на #, значить це команда, управління передається на обробник такої команди. При необхідності процесор зчитує параметри, необхідні для виконання, наприклад, назву сертифіката користувача або шлях до файлу.

Якщо немає часу для розробки такого інтерфейсу, то можна обернути сценарії функції передавати назви функцій та їх параметрів просто через параметри командного рядка — простий і звичний спосіб:

ConsoleApp.exe /test1 "Іванов Іван Іванович" ".\data\Document1.txt" ".\data\Document2.jpg"
ConsoleApp.exe /test2 "UserLogon1" "UserPassword1" ".\data\Document1.txt"

Кількість сценаріїв, звичайно обмежено і обговорюється до тестування. Тому такий варіант зручний.

Використовуючи OS Process Sampler можна передавати будь-яку кількість параметрів. Можна використовувати змінні JMeter, зчитувати параметри з CSV-файлу. Але практика показала, що зручніше написати командний файл для запуску консольного додатку. І викликати з OS Process Sampler командний файл, а не сам додаток.

Якщо сценарій повинен повертати якийсь результат в тест. Зручно реалізувати вивід на консоль цього результату у вигляді рядка. А на боці JMeter реалізувати пост-процесор, щоб обробляти параметри відповіді.

Якщо використовується готове додаток і воно не повертає певні коди відповіді при успіхах і помилках. Мінімально-необхідний post-процесор потрібен, щоб виставити статус роботи OS Process Sampler — успішно виконає програму чи ні.

Приклад для запуску wget і обробки результату його роботи пост-процесоромКомандний файл wget-download.gzip.bat для скачування великих файлів з виставленим обмеженням швидкості за допомогою wget. Командний файл приймає на вхід один параметр — адреса файлу, який потрібно завантажити, значення параметра передається з OS Process Sampler. Текст wget-download.gzip.bat:

@title %~nx0
@setlocal
@cd /d %~dp0
@rem 100 MBit/sec
@rem --progress=dot:default ( 1 KByte per line)
@rem --progress=dot:binary (384 KByte per line)
@rem --progress=dot:mega ( 3 Мбайт per line)

%~dp0wget/bin/wget.exe -S --limit-rate=20m --progress=dot:mega ^
--header "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0" ^
--header "Accept: text/html,application/xhtml+xml application/xml;q=0.9,*/*;q=0.8" ^
--header "Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3" ^
--header "Accept-Encoding: gzip, deflate" ^
--output-document=- %1 1>NUL


JSR223 PostProcessor буде використовувати скрипт на мові Groovy, що виконує розбір відповіді, що виводиться на консоль додатком wget, та заповнює відповідні поля для OS Process Sampler, щоб в балці JMeter були всі необхідні дані для аналізу відповідей. Важливо використовувати саме Groovy, так як він компілюється і виконується швидше інших, див. статтю JMeter: забудьте про BeanShell Sampler greatvovan. Текст обробника:

// prev - http://jmeter.apache.org/api/org/apache/jmeter/samplers/SampleResult.html
import java.util.regex.Matcher; 
import java.util.regex.Pattern;

//Length: 1718181 (1.6 M) [text/html]
Pattern pLength = Pattern.compile("(?im)^Length[:] ([0-9]+) ");
Matcher mLength = pLength.matcher(prev.getResponseDataAsString());
if(mLength.find())
{
int Length = Integer.parseInt(mLength.group(1));
prev.setBodySize(Length);
}

Pattern pContentType = Pattern.compile("(?im)^[ ]{2}Content[-]Type[:] (.*)");
Matcher mContentType = pContentType.matcher(prev.getResponseDataAsString());
if(mContentType.find())
{
String ContentType = mContentType.group(1);
prev.setContentType(ContentType);
}

Pattern pHeaders = Pattern.compile("(?im)^[ ]{2}([a-zA-Z].*[:].*)");
Matcher mHeaders = pHeaders.matcher(prev.getResponseDataAsString());
String headers = "";
while(mHeaders.find())
{
headers = headers + mHeaders.group(1) + "\n";
}
prev.setResponseHeaders(headers);

// HTTP/1.1 200 OK
Pattern pCodeMessage = Pattern.compile("(?im)^[ ]{2}HTTP[/]1[.][0-9] ([0-9]+) (.*)");
Matcher mCodeMessage = pCodeMessage.matcher(prev.getResponseDataAsString());
if(mCodeMessage.find())
{
String Code = mCodeMessage.group(1);
String Message = mCodeMessage.group(2);

if(Code=="200")
{
prev.setSuccessful(true);
}
else
{
prev.setSuccessful(false);
}

prev.setResponseCode(Code);
prev.setResponseMessage(Message);
}


Бібліотека і JSR223 Sampler


Хоч програми працюють прекрасно. Все ж хочеться витрачати менше ресурсів — створювати потоки, а не процеси, адже іноді немає кількох навантажувальних станцій і гігабайт ОПЕРАТИВНОЇ пам'яті. Хочеться приймати на вхід будь-які змінні JMeter. А також іноді, хочеться більшої гнучкості при формуванні сценаріїв, хочеться замість відправки псевдокода stdin додатки написати просто:

TestClient client = new TestClient();

String certificateCommonName = vars.get("certificateCommonName"); //"Іванов Іван Іванович"
String documentPath1 = vars.get("documentPath1"); //".\data\Document1.txt"
String documentPath2= vars.get("documentPath2"); //".\data\Document2.jpg"

client.authByCertificate(certificateCommonName); 
client.getInboxDocuments();
client.getContagentList();
client.sendDocument(documentPath1);
client.sendDocument(documentPath2);
client.exit();

Використовувати при цьому цикли, передачу результатів виконання одних методів на вхід інших, використовувати якусь цікаву логіку, без необхідності перемикатися між JMeter і середовищем розробки програми.

Або виконувати аутентифікацію і вихід лише один раз на кожного виртуальнульного користувача. А в рамках одного запиту з JMeter виконувати лише один запит до досліджуваної системі без додаткових часових лагів.

Є такий спосіб — використовувати JSR223 Sampler, з якого зручно викликати методи бібліотек.

У JSR223 Sampler є ряд зручних особливостей.

Можна розділити на три JSR223 Sampler ініціалізацію бібліотек, створення клієнта, підключення до системи. І в рамках одного потоку (віртуального користувача JMeter) операції виконано успішно, що дозволить заміряти час кожного кроку.

Ініціалізація клієнта до досліджуваної системи (бібліотека .NET, завантажується використовуючи jni4net). Завантажувати бібліотеки достатньо один раз для тіста:

import net.sf.jni4net.Bridge;

import java.net.URL;

Bridge.init();
Bridge.setDebug(false);
Bridge.setVerbose(false);

java.io.File clientDllFile = new java.io.File("TestClient.j4n.dll");

Bridge.LoadAndRegisterAssemblyFrom(clientFile);

Окремо для кожного потоку виконується створення примірника клієнта до досліджуваної системи:

import testClient.Client;
// Створення об'єкта
Client client = new Client();
// Збереження об'єкта в змінну "testClient" JMeter
vars.putObject("testClient", client);
// Результат виконання останньої команди запивається як тіла відповіді
// нехай відповіддю буде текстове представлення змінної client
String responseData = client;

А далі можна викликати будь-які методи для цього клієнта, наприклад, authByCertificate:

import testClient.Client;
// Отримати клієнта, створеного раніше
Client client = vars.getObject("testClient");
// Отримати параметри для виконання методу
String certificateCommonName = vars.get("certificateCommonName"); //"Іванов Іван Іванович"
// Викликати метод з параметром
client.authByCertificate(certificateCommonName);

Використовуючи jni4net, можна викликати методи бібліотек .NET. Використовуючи просто jni, можна викликати методи бібліотек Win32. Якщо бібліотека вже написана на Java, то взагалі не знадобиться додаткових прошарків. Звичайно, так можна викликати код на Python, PHP, bash, але це не завжди і потрібно.

Мова Groovy, використовуваний у JSR223 Sampler дозволяє писати компилируемые, швидкі сценарії.

І при цьому не потрібно обробляти безліч логів, як при використанні веб-додатків або простих додатків. Немає часового лага, через використання проміжних компонент.

Споживання ресурсів зведено до мінімуму. Потрібно лише вміти писати код на Groovy, а він дуже схожий на Java.

Плагін JMeter
Якщо не хочеться писати код. І при подачі навантаження не потрібно виконувати десятки методів, а достатньо виконувати однотипну операцію, але з сотнею значень параметрів. Зручно розробити плагін для JMeter. Це як бібліотека, але з графічним інтерфейсом.


Плагін для JMeter

Тут теж буде єдиний лог. Не буде тимчасового лага. Можна буде задавати параметри, не перемикаючись між додатками.

Плагін не дуже складно розробити. Разрабывал прості плагіни, розширюючи можливості існуючих, комбінуючи їх. А існуючі можна знайти в репозиторіях проектів:
Пару днів з відладчиком дадуть розуміння того, як розробити плагін.

Наприклад, плагін TailSampler (див. статтю TailSampler — паралельна відправка GET-запитів в Apache.JMeter), є комбінацією компонентів:
І містить лише пару сотень рядків вихідного коду.

Висновок

Кадр з фільму «Будинок біля озера». Спосіб спілкування (www.movpins.com)

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

Універсального способу не існує. В одній ситуації зручніше написати плагін. В інший використовувати консольний додаток. Іноді бібліотеку і скрипти на Groovy. А, буває, хочеться і свій веб-сервер підняти.

Все можливо, треба тільки вірити.

Розкажіть про те, які обмеження були знайдені в JMeter і як з ними впоралися.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.