11 августа 2011 в 10:05

Быстрое создание нагрузочных тестов на JMeter для web-сайтов из песочницы

imageДля любого программного приложения, предназначенного для массового обслуживания пользователей, необходимо проводить нагрузочное тестирование на предмет его надежности и отказоустойчивости. А так как любой web-сайт — это по своей сути система массового обслуживания, то проверка его на отказоустойчивость всегда является неотъемлемой частью разработки. Существуют различные решения для проведения нагрузочного тестирования веб-приложений. Я не буду сейчас описывать их подробно, про некоторые из них есть упоминания здесь.

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

Для тех кто ни разу не использовал JMeter, рекомендую для начала почитать базовые обзоры, например, Простой нагрузочный тест с Apache JMeter. Когда я первый раз запустил данную программу, первая мысль была разобраться во всем методом «тыка», но как выяснилось это вообще нереально, и метод «тыка» неприменим к JMeter. Поэтому если хотите его использовать, то сразу открывайте мануал, поверьте, вам придется заглядывать туда очень часто, пока полностью не разберетесь, что и как. Я же здесь сейчас опишу самое очевидное и важное, а именно: как собственно создавать нагрузочные тесты. Если бы я в свое время сразу нашел подобную статью, то сэкономил бы без малого день на изучении этой софтины.

Итак, поехали! Для интереса представим, что у нас не просто сайт, а серьезное веб-приложение с авторизацией, различными пост-запросами и т.д.

1. Запускаем JMeter.

2. Создаем Thread group:

image

Это у нас как основной workflow, в котором мы будет записывать сценарии, добавлять различную логику и элементы управления.
Теперь нужно создать собственно сценарий теста, т.е. набор различных действий для создания нагрузки на сайт. Можно создавать сценарий вручную. Это очень просто, для этого нужно добавить N-ое количество элементов HTTP Request, которые добавляются так Thread Group -> Add -> Sampler -> HTTP Request. Появляется окно настроек, представленное на рисунке ниже:

image

В соответствующие поля устанавливаем адрес сайта, порт (если нужно), путь к странице. Например, так:

image

Кроме того можно добавить параметры для запросов. И такой способ создания сценариев теста вполне приемлем для несложных сайтов. Однако в нашем случае прописывать параметры запросов для авторизации может быть утомительным занятием. Кроме того, есть нужно создать последовательность действий для обхода сайта, скажем, хотя бы по 15-ти страницам, то опять же такой вариант уже не подходит. Конечно же ручной труд не для нас, и по-хорошему это дело нужно автоматизировать. В JMeter есть такая возможность, называется запись тестов через проксирование. Т.е. мы будем выполнять любые действия через браузер, и при этом все необходимые элементы HTTP Request будут создаваться без нашего участия. Смотрим далее по пунктам, как это делается.

3. Добавляем Recording Controller (Thread Group -> Add -> Logic Controller -> Recording Controller). В данный элемент будут сохраняться все наши действия, которые мы будет делать в браузере.

4. Сразу добавим HTTP Cookie Manager (Thread Group -> Add -> Config Element -> HTTP Cookie Manager). С помощью этого элемента будет реализована работа с сессиями через cookie. В настройках данного элемента устанавливаем параметр Cookie Policy = compatibility. За описанием в мануал. Получили такую картину

image

5. Добавляем элемент HTTP Proxy Server. Добавлять его надо в раздел WorkBench (WorkBench -> Add -> Non-Test Elements -> HTTP Proxy Server), так как непосредственно в ходе тестирования этот элемент не будет принимать участия. Он нам нужен только, чтобы создать сценарии тестов. Здесь мы видим множество настроек данного элемента:

image

По сути здесь достаточно только изменить номер порта прокси-сервера, если порт по умолчанию 8080 у вас уже занят, например, можно поставить 8089. Если оставить в графе Target Controller значение Use Recording Controller, то все запросы, проходящие через прокси, будут записываться в первый попавшийся Recording Controller в нашем тест-плане. Но так как на данный момент он там всего один, то нас этот вариант устроит. Далее рекомендую обратить внимание на настройку фильтрации. Эти настройки предоставляют широкие возможности по фильтрации запросов. Это могут быть отдельные страницы, или например все js-скрипты и т.д. и т.п. Опять же в мануале они описаны достаточно хорошо.

6. В настройках браузера нужно указать адрес прокси и порт. Убедиться, что браузер ходит в интернет именно через нее, для этого перейти на любой сайт в интернете, при этом страница не должна загрузиться. Далее нам осталось в окне с настройками HTTP Proxy Server нажать на кнопку Start, запустив тем самым нашу проксю. После этого через браузер, открываем страницу тестируемого сайта, логинимся, выполняем различные действия, посещаем разных страницы, при этом сценарий уже начнет сохраняться в элемент Recording Controller. Когда вы поймете, что записанный вами сценарий уже достаточно суровый, для того чтобы задать вашему сайту жару, останавливаете прокси.
Получили, примерно, следующую картину:

image

Названия элементов могут оказаться мало о чем говорящими. Поэтому чтобы в дальнейшем было просто наблюдать за ходом теста, эти элементы имеет смысл переименовать.

7. В настройках элемента Thread Group выберите количество потоков, число итераций, время прогрева. Например, я установил такие настройки:

image

Это значит, что тестирование будет проходить в 10 потоков, будет длиться бесконечно пока, его принудительно не остановят. Время прогрева я поставил 30 сек. Это значит, что потоки будут равномерно стартовать в течении 30 секунд, т.е. каждые три секунды, будет запускаться новый поток.

8. Чтобы наблюдать результаты тестов, а также следить за ходом выполнения, нужно добавить несколько элементов мониторинга. Я обычно добавляю такие: View Results Tree, View Results in Table, Graph Results, Summary Report. Как и что они показывают, думаю, вы разберетесь сами. Единственно, что отмечу, очень полезный элемент View Results Tree, в котором можно смотреть все параметры и содержимое запросов и ответов:

image

Таким образом можно проверять, что всё работает так как надо.

Вот собственно и всё! Таким образом можно создать нагрузочный тест для вашего сайта за считанные минуты.
Напоследок, скажу еще пару полезных фич, которые реализованы в Apach JMeter.

Настройки по умолчанию

Если вы хотите задавать настройки для всех элементов HTTP Request, то это можно сделать, добавив специальный набор настроек HTTP Request Defaults (Recording Controller -> Add -> Config Element -> HTTP Request Defaults). С виду это окно очень похоже на HTTP Request. Все параметры, которые вы в нем зададите, будут использовать во всех остальных элементах данного набора. Это может быть удобно во многих ситуациях, например, когда у вас развернуто несколько вебов на разных портах, и вам периодически нужно тестировать то один, то другой. Чтобы не править один порт для всех запросов, меняем его всего лишь в одном месте в HTTP Request Defaults. Все остальные будут использовать его, если у них не задан свой.

Загрузка списка пользователей из файла

Данная задача также проста и очевидна. Если нужно натравить на ваш многострадальный веб-ресурс сразу целую свору разъяренных юзверей, которые будут хаотично нажимать на все кнопки подряд, то делается это с помощью добавления элемента CSV Data Set Config (Thread Group -> Add -> Config Element -> CSV Data Set Config).

image

В появившемся окне указываем имя, путь к файлу (если положить его рядом с файлом проекта, то достаточно указать одно имя), а также имена переменных. Эти имена вы задаете сами, они в дальнейшем будут использоваться при формировании запроса. К примеру, для связки юзер\пароль, я указал два имени переменных: USER, PASS.
Сам файл с расширением csv может выглядеть так:
userName1,pass1
userName2,pass2
userName3,pass3


Отлично, юзеров мы подали на вход джиметру. Теперь нужно сказать ему, чтобы он их заюзал там, где это требуется. Делается это так, ищем тот элемент HTTP Request, который отвечает за авторизацию. Как правило он в себе будет содержать параметры запроса, а именно: тот логин и пароль, которые вы ввели, записывая сценарий через браузер. Вместо конкретных значений имени пользователя и пароля подставляем имена наших переменных в таком формате ${USER}, ${PASS}.
У меня это выглядит так:

image

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

На этом всё, всем спасибо за внимание!
@debugx
карма
0,0
рейтинг 0,0
Пользователь
Похожие публикации
Самое читаемое Разработка

Комментарии (35)

  • 0
    Спасибо!
    А какие цифры и в каком отчете будут указывать на пиковую нагрузку, которую выдержал сервер?
    Например количество пользователей на сайте одновременно, которое потянет сайт.
    • 0
      Здесь понятие пиковой нагрузки, как таковое, отсутствует.
      Вы сами задаете количество потоков и различных запросов к веб-сайту.
      И дальше смотрите, среднее время, с которым отдаются страницы. Среднее время можно смотреть через элемент Summary Report. Если это время укладывается в ваши требования, можете поднять нагрузку и продолжить тестирование. Если нет, то считайте, что максимальную нагрузку для своего сайта вы определили, и пора заняться оптимизацией :)
  • –1
    Как только я вижу букву J в названии софтины, занимающейся нагрузочным тестированием, так сразу же у меня опускаются руки: Пока ни одной софтиной, написанной на Java, мне не удалось создать достаточной нагрузки, используя только один компьютер.
    Скажите пожалуйста — какова производительность этой софтинки?
    Сколько запросов в секунду она может генерировать на такой железке, как Core2Duo?
    • –1
      Проц не имеет значения, на компе, посылающем запросы ничего не обрабатывается
      • 0
        Наверное я что-то делаю не так.
        Угадайте — когда был запущен тест?
        content.foto.mail.ru/mail/ilvin/_myphoto/s-1331.png

        По моему разумению этот тест покажет неверные результаты, т.к. тестирующей софтине явно не хватало процессора.
      • +1
        Правда? И память тоже? А если посылать на сервер гигабайтные файлы?

        2011/08/10 19:30:02 ERROR - jmeter.threads.JMeterThread: Error processing Assertion java.lang.OutOfMemoryError: Java heap space
        at java.lang.String.toCharArray(String.java:2725)
        at org.apache.oro.text.regex.Perl5Matcher.contains(Unknown Source)
        at org.apache.jmeter.assertions.ResponseAssertion.evaluateResponse(ResponseAssertion.java:343)
        at org.apache.jmeter.assertions.ResponseAssertion.getResult(ResponseAssertion.java:189)
        at org.apache.jmeter.threads.JMeterThread.processAssertion(JMeterThread.java:609)
        at org.apache.jmeter.threads.JMeterThread.checkAssertions(JMeterThread.java:580)
        at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:359)
        at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:243)
        at java.lang.Thread.run(Thread.java:662)

        2011/08/10 19:30:05 ERROR - jmeter.threads.JMeterThread: Test failed! java.lang.OutOfMemoryError: Java heap space
        at java.io.ByteArrayOutputStream.(ByteArrayOutputStream.java:60)
        at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.readResponse(HTTPSamplerBase.java:1456)
        at org.apache.jmeter.protocol.http.sampler.HTTPSampler.readResponse(HTTPSampler.java:288)
        at org.apache.jmeter.protocol.http.sampler.HTTPSampler.sample(HTTPSampler.java:516)
        at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:965)
        at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:951)
        at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:348)
        at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:243)
        at java.lang.Thread.run(Thread.java:662)
    • +1
      Подождите, а кто сказал, что нагрузку нужно создавать непременно с одного компьютера?! Полноценный тест на нагрузочную способность с одной машины сделать очень сложно, да и нужно ли…
      Если говорить о Jmeter, то тут можно записать тест, создать батник по запуску этого теста из командной строки (JMeter это позволяет), и запускать батники с разных компьютеров. Можно для каждой машины свой тест записать.
      А по поводу производительности софтинки, однозначно быстрее, чем Load tests в Visual Studio 2010, разница заметна просто-таки невооруженным взглядом. Что касается других инструментов, то непосредственного сравнения не проводил, но думаю, что либо наравне, либо по-быстрее, всё-таки контора Apache как ни как.
      И учтите, что производительность этой тулзы на 99% зависит от пропускной способности канала, а не от железа самой машины. Я запустил ее на том серваке, где был развернут веб, так запросы стала слать почти со скоростью света :)
      • 0
        Спасибо огромное, вскоре очень понадобится это (я надеюсь).
        По поводу эмуляции параллельных запросов на разных машинах — насколько это потом удобно? Это же ведь нужно делать максимально синхронно (благо, Шедулер есть), и потом ещё анализировать результаты с разных машин и сводить вместе. Нет ли какого-нибудь плагина для него (или чего-нибудь стороннего), что позволит свести такие разбросанные отчеты в один? Или управлять централизованно с помощью какой-нибудь сетевой службы работой JMeter на разных машинах?
      • 0
        Я не склонен впадать в трепет при слове «Apache», когда есть nginx. :)
        И вопрос не в канале, т.к. он равен 1 гигабиту и полностью не выбирается во время тестирования.
        Вопрос в другом — почему у меня на Windows машине эта конкретная софтина не показывает «скорости света», а выбирает весь процессор?
        content.foto.mail.ru/mail/ilvin/_myphoto/s-1331.png
        Что я делаю не так?
        Конечно, ферма тестирующих серверов — это круто. Но почему для того, чтобы протестировать на производительность один дохлый тестовый сервер на P4, нужно городить ферму из Core2Duo?

        При этом интерфейс настройки тестов мне очень нравится. Я хочу использовать эту софтину, но не могу по причине недостаточной производительности.
        Научите меня — что нужно поднастроить в этой софтине для получения максимальной производительности. Может у нее есть функция предкомпиляции тестов?
        • 0
          Если вы использовали nginx, или хотя бы видели, как и где его используют, то вроде как должны знать, что он предназначен в первую очередь для того, чтобы отдавать статику. Сравнивать с Apache его просто бессмысленно. К тому же надо отметить, что один другому не мешает, а наоборот прекрасно дополняют друг друга, чего не сказать, например, о связке IIS + nginx.
          По вашему вопросу, попробуйте установить софтину на тот же компьютер, где развернут веб, и тогда возможно что-то прояснится. К слову сказать, канал может быть зажат. Я же не знаю, что у вас там за сетка, и кто и как ее администрирует.
          • 0
            Не обижайтесь — я не хотел Вас обидеть.
            Присмотритесь — там есть смайлик.
          • +1
            попробуйте установить софтину на тот же компьютер, где развернут веб

            Что мы в этом случае тестируем и и какова ценность результатов, которые мы получим?
            JMeter не такой уж легковесный как кажется и создает очень даже не хилую нагрузку, особенно при большом кол-ве потоков. Ибо ему надо генерировать, отправлять, получать и обрабатывать запросы и ответы. Тормозов добавляют различные View Results Tree, Summary Report и прочие, поэтому дял эмуляции нагрузки от большого кол-ва пользователей потребуется больше одной машины.

            PS
            View Results Tree полезен только на этапе отладки сценария, при нагрузочном он без полезен — нет возможности просматривать тысячи результатов, и даже вреден, т.к. создает достаточно заметную нагрузку.

            PPS
            В свое время замечал, что под линухом JMeter работает заметно быстрее чем под виндами.
            • 0
              Да, когда сценарий тестов полностью подготовлен, можно запускать JMeter в консольном режиме без каких-либо отчетов. Об этом сказано в разделе Best practices у них на сайте: jakarta.apache.org/jmeter/usermanual/best-practices.html
        • 0
          Бро, это не тупая флудилка, это мощный инструмент для проведения как функционального, так и нагрузочного тестирования. Для нагрузочного нужна ферма.
        • 0
          А как вы ее запускаете, и расскажите больше про свое окружение в котором оно работает.
          • 0
            1) Windows Vista
            2) KAS (к сожелению не могу его пристрелить — прав нет)
            3) >java -version
            java version «1.6.0_26»
            Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
            Java HotSpot(TM) Client VM (build 20.1-b02, mixed mode, sharing)
            4) Запускаю двойным кликом по ApacheJMeter.jar
            5) Памяти все это безобразие кушает 300Мб
            6) Тестирование — 100 тредов на 100 000 запросов одной единственной страницы.
            7) После запуска JMeter оба ядра процессора под 100% нагрузкой.
        • 0
          • 0
            Похоже, что эти рекомендации должны быть в этой статье на самом почетном месте!
    • +3
      Jmeter умеет кластеризоваться, т.е. можно создать ферму нагрузочных машин, управляемых как единое целое.
      • 0
        Спасибо за информацию, не знал, почитаю про это.
      • 0
        Спасибо! Это и было интересно )
    • 0
      На P4 3.0 HT, то есть ДО Core оно выдавало 200 реквестов в секунду. Потом висло. Правда версия была 2.3.1
      • 0
        Что-то странное, похоже что памяти не хватало оперативной, у нас stage сервер постоянно посылается, что-то около 500 запросов в секунду и нормально работает час или больше. Второй вариант, что-то не так с тестами.
        • 0
          2 гига было на стандартной в общем т одесктоп машине тех времен
  • 0
    блин, заигрался нагрузочным тестированием и пропустил обед :)

    спасибо большое за статью!
  • 0
    Там картинки не все грузятся, судя по всему хостинг не очень шустр. Можете перенести их на более надежный?

    А за статью спасибо!
    • 0
      сейчас они загружены на радикал.
      А какой по-надежней?
      • 0
        Ну я думаю, что тут все одобряют habrastorage.org. Вроде он как официальный даже.
      • 0
        За картинки к статьям на радикале надо карать.
  • +1
    Сравните убогий интерфейс JMeter с возможностью записи кликстрима в Tsung. Или хотя бы с дружелюбным форматом Selenium'а. Или с возможностью последнего кликать с разных «агентов».

    Вцелом — ужасающая тулза, с уймой недостатков.
    • 0
      Вот спасибо за наводку на очень интересный продукт!
      За эту ссылку и расстрелянной кармы не жалко! :)
    • 0
      Посмотрел на Tsung, кроме чуть более лучших графиков ничего интересного не заметил. А вообще, обсуждать интерфейс подобных инструментов — последнее дело. Ведь в конечном счете они запускаются из консоли.
    • 0
      А что там в цунге такое клёвое в рекордере? Типичный прокси, как и в джиметре.

      Что касается селениума — это да, для аякс-приложений делать генератор нагрузки на джиметре или подобном инструменте это жесть. Однако для селениума ферма нужна вообще здоровенная, на одной машине больше десятка браузеров (то есть фактически виртуальных пользователей) не запустишь. Хотя можно использовать BrowserMob вместо фермы, генерировать нагрузку из облака, но для интранет-приложений такой способ не катит.
  • +1
    Обратите внимание сюда, там есть еще вкусные listener-ы.
  • 0
    Благодарю за статью, но лично у меня сложилась вот какая ситуация:

    Есть сайт, развернутый в локалке, выдаем нагрузку на одну страницу в 1000 пользователей, которые постоянно на нее ломятся в течении минут 20-ти, при этом получаем 1100-1200 обрабатываемых запросов в секунду и в итоге под конец теста получаем порядка 300 эрроров:

    java.net.ConnectException: Connection timed out: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(Unknown Source)
    at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
    at java.net.PlainSocketImpl.connect(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at sun.net.NetworkClient.doConnect(Unknown Source)
    at sun.net.www.http.HttpClient.openServer(Unknown Source)
    at sun.net.www.http.HttpClient.openServer(Unknown Source)
    at sun.net.www.http.HttpClient.(Unknown Source)
    at sun.net.www.http.HttpClient.New(Unknown Source)
    at sun.net.www.http.HttpClient.New(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
    at org.apache.jmeter.protocol.http.sampler.HTTPSampler.sample(HTTPSampler.java:483)
    at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:965)
    at org.apache.jmeter.protocol.http.sampler.AccessLogSampler.sampleWithParser(AccessLogSampler.java:165)
    at org.apache.jmeter.protocol.http.sampler.AccessLogSampler.sample(AccessLogSampler.java:183)
    at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:348)
    at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:243)
    at java.lang.Thread.run(Unknown Source)

    При этом проц компа заргужен на 20-30%, сервака — 60%, причем значительную часть сервака грузит sql service (порядка 30%), в канал ничего не упирается.

    Если же запустить WCAT с теми же самыми данными, то количество обрабатываемых запросов увеличивается в 3-4 раза, загрузка проца компа и сервака снижаются примерно в 2 раза, причем sql service практически ничего не отжирает и нет никаких эрроров.

    Какой из данных тестов врет и почему? Как это выяснить?

    Заранее благодарю за помощь.

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