Monday, March 21, 2011

Нагрузочное тестирование веб сервиса с помощью soapUI

Есть такая полезная штука soapUI. Пользуюсь ей давно, но, в основном, только для того чтобы быстро проверить отдельные методы веб сервисов. Сегодня понадобилось провести нагрузочное тестирование веб сервиса авторизации, который я недавно написал.
Задача как бы тривиальная, но, вот самое сложное в такого рода задачах - это выбрать инструмент. Итак приступаем. После получаса общения с поисковой системой у меня насобирался списочек различного рода утилит. И первую, которую я решил попробовать – это младший брат soapUI, под названием loadUI. В общем, я эту штуку скачал, установил, запустил, немного подождал, увидел пользовательский интерфейс и понял что это не то что мне нужно. Интерфейс, не ужасный, очень даже красивый, и, наверное, даже слишком для такой утилиты, просто я его не понял. Половина экрана занимает раздел с устаревшими новостями и всё как-то уж очень медленно работает. Закрыв его подальше, я решил посмотреть нет ли в soapUI того что мне нужно, т.к. где-то краем глаза видел что эти две утилиты интегрируются. И мне повезло - оказывается есть ! И уже давно есть, просто раньше я не обращал внимания на то что когда импортируешь WSDL чудесной галочкой можно скачать чтобы soapUI сгенерировал набор тестов:


И следующим шагом указать настройки для генерации тестов. Для функциональных тестов мне подошёл один тест кейс в котором включены обращения к обоим методам моего веб сервиса.
Внизу самая полезная галочка, это генерация нагрузочного теста на основе функционального.


Вот как выглядит то что получилось в дереве проекта:


Теперь, когда шаблоны тестов созданы, можно приступить к эмуляции логики клиента.


В моём случае всё достаточно просто: клиент через определённые интервалы времени обращается к методу ApproveSession для подтверждения сессии и в конце работы принудительно закрывает свою сессию с помощью TerminateSession. Всё просто, но есть два нюанса:
1. Необходима поддержка HTTP сессии с помощью Cookies
2. Каждый клиент должен присылать свой уникальный ключ на сервер, который в идеале ещё и должен бы быть закриптован

Итак, оказалось, что первый пункт легко разрешается с помощью ещё одной волшебной галочки, а именно:


Разобравшись с первым вопросом я приступил ко второму. После получаса рысканья по просторам интернета, нашёл очень полезную статью, которая реально сэкономила мне немного времени, и теперь я с радостью потрачу его на блог :)
Итак, применительно к моему случаю, SOAP запрос на подтверждение сессии выглядит приблизительно следующим образом:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:ApproveSession>
         <tem:token>?</tem:token>
      </tem:ApproveSession>
   </soapenv:Body>
</soapenv:Envelope>

Чтобы обеспечить уникальнсть ключа, я буду использовать индекс потока в котором запускается клиент, выглядит это так:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:ApproveSession>
         <tem:token>token${=context.getProperty("ThreadIndex")+1}</tem:token>
      </tem:ApproveSession>
   </soapenv:Body>
</soapenv:Envelope>

Теперь, когда запросы готовы, можно добавить несколько повторов (к сожалению, не знаю как можно организовать цикл в SoapUI, если кто подскажет – буду признателен), задержки между ними и запустить нагрузочный тест:


Итак, в результате запуска теста, получен полезный отчёт. Каждый шаг был выполнен 501 раз (колонка cnt) на протяжении интервала тестирования в одну минуту. Этот интервал я установил перед запуском теста. Кроме того, среднее время отклика сервера в пределах 250 мс (колонка avg), при этом максимальное время отклика порядка 1 сек, а минимальное - 100 мс. Очень неплохо при параллельной работе 500 нагрузочных клиентов. Суммарный объём трафика для всех клиентов менее 1 мб, при этом не было ни одного отказа. В целом результат меня удовлетворил. К сожалению, не получилось сэмулировать большее количество клиентов. При попытке запустить 1000 проходит всего 50 первых запросов а дальше в лог возвращаются ошибки соединения и на короткое время пропадает доступ к интернету. Скорее всего исчерпываются свободные ресурсы на ноутбуке где я проводил тест. На сервер нареканий нет - в логах сервера всё чисто, а счётчики производительности показывают что все запросы были успешно обслужены. Но это уже детали.

Главное, что soapUI всё-таки полезная штука, и в который раз она меня выручает :)