Работа с Java VisualVM при проведении нагрузочного тестирования

в 2:22, , рубрики: jmeter, WebSphere, нагрузочное тестирование, тестирование, метки: , ,

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

Собственно, а что мы будем делать

Задача была поставлена следующая:

Необходимо, чтобы приложение выдерживало нагрузку минимум 1500 одновременных пользователей, которые будут работать по следующему сценарию:
1. Открыть страницу приложения
2. Логин в систему
3. Выгрузка большого списка записей из базы
4. Выход из системы

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

Приложение развёрнуто на IBM WebSphere Application Server 7
В качестве инструмента для нагрузки был выбран Apache JMeter 2.7
Смотреть результаты тестирования мы будем при помощи Java VisualVM

Как заставить всё это работать?

Настраиваем Application Server

Для начала развернём наше приложение на Application Server (далее WAS).
1. В адресную строку браузера ввести 'https://%hostname%:9043/ibm/console/logon.jsp
2. Используя логин и пароль администратора WAS попадаем в саму AdminConsole

Работа с Java VisualVM при проведении нагрузочного тестирования

3. Идем по Applications -> Application Types -> WebSphere enterprise applications и попадаем на страничку:
Enterprise Applications
Use this page to manage installed applications. A single application can be deployed onto multiple servers.

После установки приложения (с использованием заветной кнопочки Install) наша консоль будет выглядеть примерно так:

Работа с Java VisualVM при проведении нагрузочного тестирования

Красным прямоугольником выделено основное приложение проекта. Остальные — вспомогательные модули.

Отлично! С этим мы справились. Теперь необходимо настроить WAS для работы с Java VisualVM. Для этого в этой же AdminConsole необходимо выполнить следующие действия:
1. Servers -> Server Types -> WebSphere application servers -> server1 -> Java and Process Management -> Process definition -> Java Virtual Machine

Выберите:
Флаг
Debug Mode [false]

Debug arguments
-Xdebug -Xrunjdwp:transport=dt_socket,address=52772,suspend=n,server=y,-Dwas.debug.mode=false

Generic JVM arguments
-Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djavax.management.builder.initial= -Djava.rmi.server.hostname=%hostname% -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8686 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
* В аргументе -Djava.rmi.server.hostname= вместо %hostname% необходимо указать имя хоста, на котором установлен WAS. Знаки % не ставятся.

Работа с Java VisualVM при проведении нагрузочного тестирования

Настраиваем Java VisualVM

После установки аргументов и обязательного перезапуска сервиса WAS необходимо настроить саму Java VisualVM
1. Если у вас стоит Sun JDK 6u7 и выше, то VisualVM у вас уже есть. Рекомендуется работать с последней версией Sun JDK 7, Java VisualVM находится в каталоге $JAVA_HOMEjdk1.7.0binjvisualvm
Также Java VisualVM можно скачать отдельно
2. Запустите Java VisualVM. При первом запуске VisualVM может попросить логин и пароль, не отказывайте ей в этом
3. Общий вид Java VisualVM

Работа с Java VisualVM при проведении нагрузочного тестирования

Как видно, локально определились несколько приложений, в том числе и сама VisualVM.

4. В меню «Tools -> Plug-ins» на вкладке Available Plugins указаны доступные плагины, при желании выберите и установите нужные. Для нашей цели они не понадобятся, но знать о них стоит.
5. Добавьте тот удаленный хост, для которого проводились предыдущие настройки:

Работа с Java VisualVM при проведении нагрузочного тестирования

6. Добавим JMX Connection. Обязательно укажите порт 8686 после имени хоста и нажмите Оk

Работа с Java VisualVM при проведении нагрузочного тестирования

7. После подключения к удалённому хосту выберите Open JMX Connection и вы попадёте в Overview нужного процесса

Работа с Java VisualVM при проведении нагрузочного тестирования

Здесь нас будет интересовать вкладка Sampler (он же профайлер). У профайлера есть два режима: CPU и Memory. Первый профилирует методы с точки зрения проведённого в них времени, второй — с точки зрения созданных и уничтоженных объектов. К сожалению Memory sampling не поддерживается для удалённых приложений.
Для более детального просмотра выберите нужный метод и нажмите кнопку Snapshot, которая вызовет дерево методов (классов/пакетов), используемых для дальнейшего анализа.

Важно!


Стоит обратить внимание на то, что данный performance-профайлер является инструментирующим. То есть переписывает код приложения, добавляя в него вызовы в профайлер.
Инструментирующие профайлеры имеют достаточно большие накладные расходы, но зато дают самые точные результаты. Работа такого профайлера может достаточно сильно искажать работу приложения, но накладные расходы в теории будут равномерно распределяться по всем методам.

Создаем проект в JMeter

Как создавать проект в JMeter на Хабре писали уже неоднократно, к тому же мануалы никто не отменял, поэтому в этой части статьи будет рассказано лишь о тех нюансах, с которыми мы столкнулись.

Localhost

Как гласит замечательный мануал, для работы в JMeter необходимо Configure your brower to use the JMeter HTTP Proxy следующим образом:

Работа с Java VisualVM при проведении нагрузочного тестирования

А вот что делать, если ты работаешь в России, а сервер приложений развёрнут в ЦР Днепропетровска, да к тому же корпоративная политика IT безопасности блокирует все соединения, не использующие нужный Proxy там не написано. Также было установлено, что если работать через корпоративный Proxy, то запись в Recording Controller не шла.

В нашем случае помог следующий «финт ушами»:
Подключались к приложению через корпоративный Proxy, затем в настройках браузера меняли настройки на localhost, перезагружали страницу и (о чудо!) работали на удаленном хосте через localhost. Дальше у нас было от силы 5-7 минут, чтобы в темпе «дикой паники» записать сценарий, после чего automatic configuration script менял настройки Proxy на прежние.

Имя нам Легион!

Создаем пользователей и скармливаем их JMeter.
Был написан простенький скрипт, который добавил в таблицу tUsers 1500 записей с уникальными логинами TEST1-TEST1500. Пароль был у всех один: 123456
Далее в JMeter был добавлен элемент СSV Data Set Config

Работа с Java VisualVM при проведении нагрузочного тестирования

Теперь в дереве записанных реквестов находимо найти элемент, отвечающий за логин в систему. У нас это был …/userLogin.web, который имел следующее значение:
LoginService|login|java.lang.String/2004016611|TEST1|1|2|3|4|1|5|6|
Здесь мы видим наши логин и пароль. Почему JMeter записал пароль 123456 как 1|2|3|4|1|5|6| для меня до сих пор остаётся загадкой.

Теперь наша задача сводится к следующему:
1. Создать *.csv файл и поместить туда 1500 записей вида
LoginService|login|java.lang.String/2004016611|TEST1|1|2|3|4|1|5|6|
.
.
.
LoginService|login|java.lang.String/2004016611|TEST1500|1|2|3|4|1|5|6|
2. Положить этот файл в одну директорию с проектом
3. Показать JMeter, что нужно их брать из этого файла

Небольшие затруднения возникли на первом этапе.
Скопировать в ячейки А1 и А2
LoginService|login|java.lang.String/2004016611|TEST1
LoginService|login|java.lang.String/2004016611|TEST2
в Excel и растянуть до А1500
LoginService|login|java.lang.String/2004016611|TEST1500
проблем не составило. Также всё было просто и с оставшейся частью 1|2|3|4|1|5|6|, которую мы скопировали 1500 раз без изменений в ячейки В1-В1500. Но вот после переноса всего этого добра в текстовый файл получилось не очень красиво:
LoginService|login|java.lang.String/2004016611|TEST1| 1|2|3|4|1|5|6|

Понятно, что лишние пробелы нам совершенно ни к чему. Но вот как их убрать? Ручками править 1500 записей – не наш метод. Открыв файл через Notepad++, попытались убрать эти пробелы с помощью Replace, но, к сожалению, для него совершенно без разницы 1 там пробел или 10. Он их не видит и может заменять только символы.
Тут нам на выручку пришел EmEditor. Он всё это спокойно делает:

Работа с Java VisualVM при проведении нагрузочного тестирования

После этого случая EmEditor сильно вырос в моих глазах. Как показала практика, этот текстовый редактор выручает и в других случаях, например, когда нужно изменить что-нибудь в *.xml файле уже развёрнутого приложения. Тот же блокнот или Notepad++ пасуют перед этой задачей и ругаются на access denied, а EmEditor нет.

Переименовали подготовленный текстовый файл в 1500.csv и положили в одну папку с проектом.

Теперь осталось объяснить JMeter как всё это использовать.
Для этого в СSV Data Set Config указываем файл и задаём имя переменной

Работа с Java VisualVM при проведении нагрузочного тестирования

А в …/userLogin.web указываем эту переменную в виде ${VariableName}

Работа с Java VisualVM при проведении нагрузочного тестирования

Увеличиваем кучу

В директории apache-jmeter-2.7bin находим файл jmeter.bat и открываем его любимым текстовым редактором.
Находим там часть

Работа с Java VisualVM при проведении нагрузочного тестирования

И для комфортной работы заменяем
set HEAP=-Xms512m -Xmx512m
на
set HEAP=-Xms1024m -Xmx1024m
Об этом также написано и в мануале к запуску jmeter (2.4 Running JMeter)

Последние штрихи

Теперь у нас практически всё готово для запуска сценария. Осталось только подключиться по RDP к нашему удалённому хосту и проверить, что всё хорошо (снять параметры сервера приложений до начала тестирования):

Работа с Java VisualVM при проведении нагрузочного тестирования

Как видно, всё в пределах разумного. Также смотрим, сколько памяти на себя забирает процесс java.exe, которым себя обозначает WAS.

Тест, настало твоё время

Запускаем тест и смотрим как 1500 виртуальных юзеров радостно ломанулись в наше многострадальное приложение. Мы же тем временем опять переключимся на удалённый стол и посмотрим, что же там происходит:

Работа с Java VisualVM при проведении нагрузочного тестирования

CPU сервера приложений было занято на 100% во время всего теста, что совсем не хорошо. Так и упасть не долго.
Смотрим теперь в VisualVM, картина не очень радостная:

Работа с Java VisualVM при проведении нагрузочного тестирования

Заходим в Sampler и смотрим, что же так грузит CPU:

Работа с Java VisualVM при проведении нагрузочного тестирования

Смотрим в SystemError лог сферы:

R log4j:WARN Continuable parsing error 209 and column 14
R log4j:WARN Содержимое элемента типа «logger» должно соответствовать "(param*,level?,appender-ref*)".
R log4j:WARN No appenders could be found for logger (org.springframework.web.context.support.XmlWebApplicationContext).
R log4j:WARN Please initialize the log4j system properly.
R log4j:WARN See logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

… и понимаем, кто тут виноват.

Проверяем наше предположение.
Для этого находим папку с развернутым приложением в %WAS_HOME%AppServerprofilesAppSrv01installedApps%HostName%Node01Cellapp.earapp.warWEB-INF. Находим там файл log4j.xml и в нем везде, где встречаются конструкции вида />, заменяем этот уровень на значение off. После этого перезапускаем сервис WAS.

Запускаем тест ещё раз:

Работа с Java VisualVM при проведении нагрузочного тестирования

Совсем другое дело!

Результаты

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

Если у Вас возникнут вопросы, то я с удовольствием на них отвечу. Спасибо за внимание.

Автор: Torrero2525

* - обязательные к заполнению поля