- PVSM.RU - https://www.pvsm.ru -
Плагин упрощает загрузку встроенных ресурсов, позволяет параллельно выполнять указанные GET-запросы. Делая тест максимально близким к работе браузера по составу загружаемых ресурсов и по способу загрузки этих ресурсов.
TailSampler [1] выручает если нужно:
HTTP Request Tail преобразует список ссылок в HTML-документ, загрузка встроенных ресурсов которого создаст GET-запрос по каждой из указанных ссылок.
[2]
Рисунок 1. Процесс подготовки данных для плагина TailSampler и их использование
Стандартный способ получения HTML-документа по протоколу HTTP в JMeter — использование HTTP Request sampler. В HTTP Request есть простой способ запросить встроенные ресурсы страницы — галочка [v] Retrieve Embedded Resources. Стандартным парсером, формирующим ссылки на ресурсы страницы является LagartoBasedHtmlParser. Парсер можно поменять в настройке htmlparser.classname файла jmeter.properties.
Исследование парсеров Apache.JMeter для пяти популярных сайтов приведено в статье «Выбираем html-парсер для Apache.JMeter»:
При использовании парсеров загружаются почти все нужные ресурсы. Но для разных сайтов полнота загрузки разная. Так если веб-сайт реализован на Microsoft Silverlight, то эффективность работы парсера Apache.JMeter будет около 0%. Тогда как, используя, TailSampler, можно будет подать нагрузку, аналогичную работе браузера простым способом.
[4] Рисунок 2. Сайт atlas.mos.ru [5] в браузере — 85 запросов к основному домену |
[6] Рисунок 3. Сайт atlas.mos.ru [5] в JMeter — 2 запроса к основному домену
|
[7] Рисунок 4. Трассировку выполнения запросов можно увидеть в webpagetest.org [8] |
[9] Рисунок 5. Браузер выполняет 85 запросов к основному домену, а JMeter только 2 — эффективность 2,35% , см. логи в google docs [10] |
При открытии сайта atlas.mos.ru, активно использующего AJAX, видна разница:
2
GET-запроса, если работает LagartoBasedHtmlParser, HTTP Request, JMeter 3.0;85
GET-запросов, если работает браузер Chrome.
Таким образом, при использовании HTTP Request с настройкой [v] Retrieve Embedded Resources для адреса atlas.mos.ru 83
GET-запрос не будет отправлен.
Маловато будет
«Падал прошлогодний снег»
Чтобы сэмулировать отправку 83
GET-запроса, нужно будет добавить 83
компонента HTTP Request в скрипт JMeter:
Добавленные 83
HTTP Request будут обрабатываться последовательно друг за другом — браузер же отправляет запросы на встроенные ресурсы параллельно:
[11]
Рисунок 6. Отчёт по загрузке сайта pflb.ru в Firefox — http://www.webpagetest.org/result/160319_RQ_Q3W/1/details/ [12] — видны группы параллельной загрузки по 6
запросов
Таким образом, используя только HTTP Request не удастся полностью повторить загрузку встроенных ресурсов так, чтобы точно замерить время загрузки html-страницы со всеми подзапросами.
[13]
Рисунок 7. HTTP Request не позволяет увидеть картину целиком, реализовать хвост подзапросов поможет HTTP Request Tail
Плагин HTTP Request Tail для JMeter создан в качестве альтернативы Tile Server — сервису на python, описание смотри ниже.
Первое знакомство с сервисом Tile Server произошло, когда коллеги Женя Бороденков и Максим Конышев рассказывали про нагрузочное тестирование веб-проекта, загружающего большие изображения кусочками, тайлами. Тогда мы решали задачу нагрузочного тестирования одной из версий этого веб-проекта, использующей SilverLight на клиенте и потоковое получение содержимого от сервера по протоколу SOAP/MSBin1. Послать из JMeter запросы по протоколу SOAP/MSBin1 и обработать ответы на них мы сначала не знали как, обсуждали варианты.
Рассказ был примерно таким:
— Если бы тут был Вова, он бы сказал использовать промежуточный сервис для формирования нужных запросов.
— Промежуточный сервис, это слишком сложно (отвечал им). Давайте напишем плагин для JMeter. Плагин — просто и надёжно.
— Вот когда было предыдущее тестирование, Андрей Пищулин написал сервис Tile Server на python, этим сервисом до сих пор пользуемся, сервис для работы с тайлами:
- JMeter отправляет серверу Tile Server список ссылок методом POST через HTTP Request;
- Tile Server реализует веб-сервер, принимает список ссылок, формирует из ссылок html-документ со списком iframe-ов, указывающих на ссылки и возвращает html-документ JMeter;
- JMeter парсит html-документ и выполняет нужные GET-запросы, как подзапросы.
Давай делать также.
— Хорошо, давай сделаем промежуточный сервис для реализации работы с SOAP/MSBin1.
Забегая вперёд скажу, сделали мы также, как когда-то. Сделали прокси-сервис на .NET, который формировал запросы по SOAP/MSBin1 — JMeter посылал команды этому сервису по SOAP/XML, а сервис посылал запросы к нагружаемому узлу уже по SOAP/MSBin1 и возвращал ответы к JMeter.
И при высокой нагрузке прокси-сервис стал узким местом, не смог он генерировать запросы и обрабатывать ответы так, чтобы нагружаемые серверы приуныли и прилегли. Нагрузку тестируемые серверы получили, но если они отвечали прокси-сервису за 10
секунд, прокси-сервис отвечал JMeter-у за 110
секунд. По статистике из логов JMeter выходило, что нагружаемый сервис приуныл, и да, нагрузка подавалась хорошая, но нагружаемый сервис отвечал бодро, бодрее, чем свидетельствовали логи JMeter. Оперативное добавление подробного логирования в прокси-сервис исправило ситуацию, но когда прокси-сервис зависал, то и логирование на нём запаздывало — надо было масштабировать промежуточный сервис или переписывать его полностью, один экземпляр не тянул на роль «Царь-пушки».
Прокси-сервис стал точкой отказа. Тогда вернулись к идее плагина для JMeter, и сделали из JSR223, библиотек JNA и прокси-клиента на .NET пулемёт для работы по протоколу SOAP/MSBin1, вышло здорово. Плагину уже не приходится обрабатывать несколько входящих потоков. Накладных расходов на оперативную память, конечно, больше, но работает это быстрее.
Тогда же возникла идея написать sampler JMeter на java, на замену Tile Server, вдруг и он является точкой отказа при нагрузке. Даже название будущего sampler-а появилось — «HTTP Request Tail» или «Tail Sampler». Из-за плохого знания английского языка услышал слово «Tile», как «Tail», немного не понял, причём тут «тайлы» и слово, которое переводится как «хвост». Глухие телефоны, хвост так хвост, образ русалки дополнил картину. Задумка закрепилась, идея ясна, название есть. Оставалось самое малое — сделать. Тут помогла Саша Перевозчикова Sanchez92 [15] — эксперт по разработке плагинов.
Претензий к Tile Server не имею, коллеги говорят — это быстрый и надёжный инструмент. Плагин создавался из любопытства и интереса к новому для меня инструменту JMeter, и Сашу надо было чем-то занять, а то скучала девица.
Все имена в этой истории невымышленные, явно или косвенно плагин «HTTP Request Tail» сделали:
[16]
Рисунок 9. Настройки по умолчанию
По умолчанию используются настройки:
4
— по умолчанию используется значение 4, это значение используется JMeter в качестве базового:
4
будет посылать до 4 запросов одновременно, каждый поток будет использовать по 1 постоянному соединению на каждый домен:
6
одновременных запросов на каждый домен (см. about:config
):
256
— network.http.max-connections — максимальное число соединений;6
— network.http.max-persistent-connections-per-server — максимальное число постоянных соединений с сервером (keepalive);32
— network.http.max-persistent-connections-per-proxy — максимальное число постоянных соединений с прокси-сервером (keepalive);6
, вместо стандартного значения 4
.Неиспользуемые настройки — настройки для POST-запросов, значения никак не используются ни главным запросом ни подзапросами:
Главный запрос генерируется, а не отправляется, на него настройки для POST-запросов не действуют. Подзапросы используют метод GET, для них также не действуют настройки для POST-запросов.
Остальные настройки действуют на подзапросы.
HTTP Request Tail является наследником HTTP Request, описание настроек можно посмотреть в документации на HTTP Request:
[17]
Рисунок 10. Настроенный HTTP Request Tail
Ссылки на встроенные ресурсы указываются в текстовом поле Embedded resources. Можно указывать относительные и абсолютные ссылки.
Описание формата абсолютных ссылок смотри в RFC: https://tools.ietf.org/html/rfc3986 [18].
Абсолютные ссылки начинаются с протокола:
file://
http://
https://
Другие протоколы не обработаются HTTP Request Tail. Примеры абсолютных ссылок:
file://C:DatahtmlDocument.html#Part1
http://www.pflb.ru/ [19]
https://yandex.ru/?q=Testing&client=Mozilla [20]
Относительные ссылки дополняются значениями полей:
file
, http
, https
.Пример относительных ссылок:
image1.png
/images/image1.png
/ResourceGenerator.aspx?id=0121
subFolder/style.css
subFolder/1/2/3/test.php
Для параметризации GET-запросов можно использовать переменные и функции JMeter. Пример:
${variable_URL}
/search.php?q=${variable_Query_String}
/search.php?q=${variable_Query_String}&client=Mozilla
/search.php?q=${__urlencode(${variable_Query_String})}&client=Mozilla
При формировании html-страницы из ссылок используется html-экранирование. Поэтому при написании ссылок можно использовать:
<
, >
, &
и другие;
Структура html-страницы не нарушится, ссылки обработаются корректно и в полном объёме.
Полный список html-сущностей для html4 смотри тут:
Если какая-то сущность из спецификации не экранируется, то оформите замечание к плагину.
Не нужно предварительно экранировать специальные символы. Так если есть необходимость указать URL вида:
/search.php?q=Testing&client=Mozilla
— правильно.
То так и надо писать — просто &
, заранее экранировать на &
не надо:
/search.php?q=Testing&client=Mozilla
— неправильно.Замечено, что если в адресе есть unicode-символ, например, ®, Ω, π, ≈:
/search.php?q=Microsoft®
И в настройке Implementation стоит значение Java
, то в подзапросе unicode-символ будет заменен на квадратик:
/search.php?q=Microsoft□
При запуске JMeter из Windows с помощью bat-файла кодировкой для java назначается windows-1251
, предполагаю это причина замены unicode-символа на квадратик. Чтобы задать кодировку нужно указать в bat-файле аргумент для java: -Dfile.encoding=UTF-8
. При использовании HttpClient4
и HttpClient3.1
такой нежелательной трансформации не происходит.
[21]
Рисунок 11. Ответ на основной запрос — генерируемый ответ
Ответ на основной запрос генерируется. Запроса нет, есть только тело ответа.
Тело ответа представляет собой html-документ, текст с кодировкой UTF-8, где для каждой ссылки на встроенный ресурс сгенерирован тег iframe
.
Пример документа:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Embedded resources</title>
</head>
<body>
<iframe src="http://www.google-analytics.com/analytics.js"></iframe>
<iframe src="/sites/all/themes/pro/static/img/icons.png"></iframe>
<iframe src="sites/all/themes/pro/static/img/main_3_block90-s.png"></iframe>
<iframe src="http://pflb.ru/sites/all/themes/pro/static/img/footer-shadow.png"></iframe>
<iframe src="http://staticxx.facebook.com/connect/xd_arbiter.php"></iframe>
</body>
</html>
[22]
Рисунок 12. Статистика выполнения генерируемого запроса
При написании статьи про парсеры JMeter в комментариях появился разработчик JMeter Philippe M. philmdot [23] и попросил запостить дефект на счёт рекурсивной обработки:
Планирую запостить дефект, и даже исправить его. Сделав так, чтобы для ответов на запросы из тегов img
не выполнялся рекурсивный поиск ссылок на ресурсы. Чтобы в JMeter парсинг работал также, как это делает браузер. Вот если iframe
, то надо выполнять парсинг, а если просто img
, то выполняется единичный запрос.
И тогда же надо будет изменить плагин TailSampler так, чтобы при генерации использовались теги img
вместо тегов iframe
.
Сегодня Philippe написал, что хотел бы увидеть этот код в ядре JMeter, что это будет хороший способ работы с AJAX. Попробую успеть в этом году, будет интересный опыт.
Корневой запрос хоть и не отправляется, но попадает в лог:
Если стоит настройка Follow Redirect, то для каждого встроенного ресурса с кодом ответа 302
(Found):
Редкий, но возможный эффект — загрузка встроенных ресурсов для встроенного ресурса:
В планах ограничить глубину рекурсии до настраиваемого из интерфейса плагина параметра в 3 уровня по умолчанию. Браузер при загрузке картинки (тег img) не выполняет для неё загрузку встроенных ресурсов. Тут же, все ресурсы обёрнуты в тег iframe, и Apache.JMeter в настоящий момент не различает, для какого тега осуществлялся запрос — всегда парсит ответ на предмет подзапросов, если Content Type ответа подходящий.
[25]
Рисунок 13. Виден первый запрос test_server.ru, который не выполнялся на самом деле (эффект «+1 запрос»). Виден каскад перенаправлений (эффект «Визуальный обман для ответа 302») и подзапросов для подзапросов (эффект «Рекурсия»).
Если снять галочку [ ] Retrieve All Embedded Resources или не указать ни одной ссылки в Embedded resources, то в логах будет написано, что запрос отправился мгновенно, и ответ на него пришел мгновенно.
Описание временных характеристик:
0
;0
.Исходный код в каталоге:
file://
для подзапросов;HttpClient3.1
из настройки Implementation для подзапросов;HttpClient4
из настройки Implementation для подзапросов;Java
из настройки Implementation для подзапросов;Другие каталоги вспомогательные, служат для удобства отладки проекта.
Форма TailUrlConfigGui является модификацией главной формы HTTP Request из Apache.JMeter 2.13, откуда удалены поля для редактирования тела запроса и задания списка параметров, но добавлено одно большое поле для ввода списка ссылок.
А внешний вид TailHttpSamplerGui также является копией HTTP Request, где теперь применяется новый главный элемент управления TailUrlConfigGui.
Тут не обошлось без копипасты. Пошел на этот шаг, чтобы HTTP Request Tail почти не отличался от HTTP Request.
Но в JMeter 3.0 внешний вид HTTP Request был изменён, элементы управления переставлены местами. Теперь HTTP Request Tail отличается HTTP Request для JMeter 3.0. Но это на работу не влияет.
Хотелось по максимуму использовать существующий код, но копипастой заниматься не хотелось. Поэтому были созданы классы Wrapper-ы, благодаря котором методы sample, notifyFirstSampleAfterLoopRestart и threadFinished стали доступными.
Код класса, выполняющего экранирование взят с сайта ibm.com: www.ibm.com/developerworks/ru/library/se-prevent/index.html [26]
Таблица html-сущностей расширена за счёт RFC с описанием HTML4.
[28]
Рисунок 14. Теперь плагин HTTP Request Tail доступен в JMeter
Пример каталога:
D:TOOLSapache-jmeter-2.13libext D:TOOLSapache-jmeter-2.13libextru.pflb.jmeter.samplers.TailSampler.jar D:TOOLSapache-jmeter-3.0libext D:TOOLSapache-jmeter-3.0libextru.pflb.jmeter.samplers.TailSampler.jar
Apache.JMeter 2.13 собран с использованием Java 6. И если собрать плагин TailSampler с использованием, например, OpenJDK 1.7.0_09-icedtea, и запустить Apache.JMeter 2.13 + собранный плагин на компьютере, где есть только Java 6, то Apache.JMeter 2.13 запустится, а плагин нет. В результате их связка работать не будет. Вопрос сборки проектов и библиотек для различных версий Java и их совместимости заслуживает отдельной инструкции.
Apache.JMeter 3.0 собран с использованием Java 7. Плагин TailSampler нужно собирать с использованием Java 7 или той версии Java, которая будет использоваться для запуска JMeter и плагина.
Автор: polarnik
Источник [29]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/205285
Ссылки в тексте:
[1] TailSampler: https://github.com/pflb/Jmeter.Plugin.TailSampler
[2] Image: https://habrastorage.org/files/6ef/258/983/6ef25898340a4970952bccb41c52f0fa.png
[3] https://habrahabr.ru/post/308254/: https://habrahabr.ru/post/308254/
[4] Image: https://habrastorage.org/files/1bf/9b6/0bb/1bf9b60bb308436185939c92dfb486aa.png
[5] atlas.mos.ru: https://atlas.mos.ru
[6] Image: https://habrastorage.org/files/061/9d5/e15/0619d5e1561c41ddb1c71d8da98c5172.png
[7] Image: https://habrastorage.org/files/462/219/bec/462219bece014910bb052df61433b873.png
[8] webpagetest.org: https://www.webpagetest.org/result/161014_ZM_1HRA/1/details/
[9] Image: https://habrastorage.org/files/c29/afb/df7/c29afbdf73ee415994e00040119c7e70.png
[10] google docs: https://docs.google.com/spreadsheets/d/1kL3XdDdg7KYSe64iKWlPEL-1jhTwp8v-9eu0IWTnEUk/edit?usp=sharing
[11] Image: https://habrastorage.org/files/9b7/e30/e9f/9b7e30e9fec8482ea7229eeb3ebf27c3.png
[12] http://www.webpagetest.org/result/160319_RQ_Q3W/1/details/: http://www.webpagetest.org/result/160319_RQ_Q3W/1/details/
[13] Image: https://habrastorage.org/files/6df/8e9/03d/6df8e903de274468a7372d3e8f8afbef.jpg
[14] Image: https://habrastorage.org/files/b8e/0db/c6d/b8e0dbc6d298450c9ddb0ee4ac9aea0e.jpg
[15] Sanchez92: https://habrahabr.ru/users/sanchez92/
[16] Image: https://habrastorage.org/files/b00/fe1/2ab/b00fe12ab7c44ed6b20decd841ba9fc2.PNG
[17] Image: https://habrastorage.org/files/401/7bb/e33/4017bbe3372d4f6f9d846506dcbafdac.png
[18] https://tools.ietf.org/html/rfc3986: https://tools.ietf.org/html/rfc3986
[19] http://www.pflb.ru/: http://www.pflb.ru/
[20] https://yandex.ru/?q=Testing&client=Mozilla: https://yandex.ru/?q=Testing&client=Mozilla
[21] Image: https://habrastorage.org/files/9d7/613/9e7/9d76139e750242c5a9145dd949fa100f.PNG
[22] Image: https://habrastorage.org/files/80b/699/662/80b6996620724c6293e4e6ca4a3ffa04.PNG
[23] philmdot: https://habrahabr.ru/users/philmdot/
[24] https://habrahabr.ru/post/308254/#comment_9767524: https://habrahabr.ru/post/308254/#comment_9767524
[25] Image: https://habrastorage.org/files/640/bff/594/640bff5949084b1e98f03dc3295db0a9.png
[26] www.ibm.com/developerworks/ru/library/se-prevent/index.html: http://www.ibm.com/developerworks/ru/library/se-prevent/index.html
[27] github.com/pflb/Jmeter.Plugin.TailSampler/releases: https://github.com/pflb/Jmeter.Plugin.TailSampler/releases
[28] Image: https://habrastorage.org/files/d08/636/3bd/d086363bd0154c90904e7a1f9f646bf5.png
[29] Источник: https://habrahabr.ru/post/312352/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.