- PVSM.RU - https://www.pvsm.ru -
При разработке любого крупного WEB-приложения рано или поздно встает вопрос о проведении нагрузочного тестирования. Такой вопрос возник и в нашем проекте. О том, как мы его решили вы сможете узнать из этой статьи.
Задача была поставлена следующая:
Необходимо, чтобы приложение выдерживало нагрузку минимум 1500 одновременных пользователей, которые будут работать по следующему сценарию:
1. Открыть страницу приложения
2. Логин в систему
3. Выгрузка большого списка записей из базы
4. Выход из системы
Приложение развёрнуто на IBM WebSphere Application Server 7
В качестве инструмента для нагрузки был выбран Apache JMeter 2.7
Смотреть результаты тестирования мы будем при помощи Java VisualVM
Для начала развернём наше приложение на Application Server (далее WAS).
1. В адресную строку браузера ввести 'https://%hostname%:9043/ibm/console/logon.jsp
2. Используя логин и пароль администратора WAS попадаем в саму AdminConsole
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) наша консоль будет выглядеть примерно так:
Красным прямоугольником выделено основное приложение проекта. Остальные — вспомогательные модули.
Отлично! С этим мы справились. Теперь необходимо настроить 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. Знаки % не ставятся.
После установки аргументов и обязательного перезапуска сервиса WAS необходимо настроить саму Java VisualVM
1. Если у вас стоит Sun JDK 6u7 и выше, то VisualVM у вас уже есть. Рекомендуется работать с последней версией Sun JDK 7, Java VisualVM находится в каталоге $JAVA_HOMEjdk1.7.0binjvisualvm
Также Java VisualVM можно скачать отдельно [1]
2. Запустите Java VisualVM. При первом запуске VisualVM может попросить логин и пароль, не отказывайте ей в этом
3. Общий вид Java VisualVM
Как видно, локально определились несколько приложений, в том числе и сама VisualVM.
4. В меню «Tools -> Plug-ins» на вкладке Available Plugins указаны доступные плагины, при желании выберите и установите нужные. Для нашей цели они не понадобятся, но знать о них стоит.
5. Добавьте тот удаленный хост, для которого проводились предыдущие настройки:
6. Добавим JMX Connection. Обязательно укажите порт 8686 после имени хоста и нажмите Оk
7. После подключения к удалённому хосту выберите Open JMX Connection и вы попадёте в Overview нужного процесса
Здесь нас будет интересовать вкладка Sampler (он же профайлер). У профайлера есть два режима: CPU и Memory. Первый профилирует методы с точки зрения проведённого в них времени, второй — с точки зрения созданных и уничтоженных объектов. К сожалению Memory sampling не поддерживается для удалённых приложений.
Для более детального просмотра выберите нужный метод и нажмите кнопку Snapshot, которая вызовет дерево методов (классов/пакетов), используемых для дальнейшего анализа.
Стоит обратить внимание на то, что данный performance-профайлер является инструментирующим. То есть переписывает код приложения, добавляя в него вызовы в профайлер.
Инструментирующие профайлеры имеют достаточно большие накладные расходы, но зато дают самые точные результаты. Работа такого профайлера может достаточно сильно искажать работу приложения, но накладные расходы в теории будут равномерно распределяться по всем методам.
Как создавать проект в JMeter на Хабре писали уже неоднократно, к тому же мануалы никто не отменял, поэтому в этой части статьи будет рассказано лишь о тех нюансах, с которыми мы столкнулись.
Как гласит замечательный мануал [2], для работы в JMeter необходимо Configure your brower to use the JMeter HTTP Proxy следующим образом:
А вот что делать, если ты работаешь в России, а сервер приложений развёрнут в ЦР Днепропетровска, да к тому же корпоративная политика 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
Теперь в дереве записанных реквестов находимо найти элемент, отвечающий за логин в систему. У нас это был …/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. Он всё это спокойно делает:
После этого случая EmEditor сильно вырос в моих глазах. Как показала практика, этот текстовый редактор выручает и в других случаях, например, когда нужно изменить что-нибудь в *.xml файле уже развёрнутого приложения. Тот же блокнот или Notepad++ пасуют перед этой задачей и ругаются на access denied, а EmEditor нет.
Переименовали подготовленный текстовый файл в 1500.csv и положили в одну папку с проектом.
Теперь осталось объяснить JMeter как всё это использовать.
Для этого в СSV Data Set Config указываем файл и задаём имя переменной
А в …/userLogin.web указываем эту переменную в виде ${VariableName}
В директории apache-jmeter-2.7bin находим файл jmeter.bat и открываем его любимым текстовым редактором.
Находим там часть
И для комфортной работы заменяем
set HEAP=-Xms512m -Xmx512m
на
set HEAP=-Xms1024m -Xmx1024m
Об этом также написано и в мануале [3] к запуску jmeter (2.4 Running JMeter)
Теперь у нас практически всё готово для запуска сценария. Осталось только подключиться по RDP к нашему удалённому хосту и проверить, что всё хорошо (снять параметры сервера приложений до начала тестирования):
Как видно, всё в пределах разумного. Также смотрим, сколько памяти на себя забирает процесс java.exe, которым себя обозначает WAS.
Запускаем тест и смотрим как 1500 виртуальных юзеров радостно ломанулись в наше многострадальное приложение. Мы же тем временем опять переключимся на удалённый стол и посмотрим, что же там происходит:
CPU сервера приложений было занято на 100% во время всего теста, что совсем не хорошо. Так и упасть не долго.
Смотрим теперь в VisualVM, картина не очень радостная:
Заходим в Sampler и смотрим, что же так грузит CPU:
Смотрим в 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 [4] for more info.
… и понимаем, кто тут виноват.
Проверяем наше предположение.
Для этого находим папку с развернутым приложением в %WAS_HOME%AppServerprofilesAppSrv01installedApps%HostName%Node01Cellapp.earapp.warWEB-INF. Находим там файл log4j.xml и в нем везде, где встречаются конструкции вида />, заменяем этот уровень на значение off. После этого перезапускаем сервис WAS.
Запускаем тест ещё раз:
Совсем другое дело!
В этой статье мы рассмотрели полный цикл настройки окружения для проведения нагрузочного тестирования WEB-приложения. Понятно, что одним только log4j дело не ограничилось, впоследствии было проведено множество других доработок, но основной смысл работы, надеюсь, ясен.
Если у Вас возникнут вопросы, то я с удовольствием на них отвечу. Спасибо за внимание.
Автор: Torrero2525
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/testirovanie/10675
Ссылки в тексте:
[1] отдельно: http://java.net/projects/visualvm
[2] мануал: http://jmeter.apache.org/usermanual/jmeter_proxy_step_by_step.pdf
[3] мануале: http://jmeter.apache.org/usermanual/get-started.html
[4] logging.apache.org/log4j/1.2/faq.html#noconfig: http://logging.apache.org/log4j/1.2/faq.html#noconfig
Нажмите здесь для печати.