среда, 12 октября 2022 г.

Тестирование производительности

1 Обзор

1.1 Что такое производительность и что значит быстро

Тестирование производительности

Общие принципы

Тестирование - это исследование системы с целью получения информации о качестве и предоставлении этой информации заинтересованным лицам.


Качество


Тестирование производительности - это исследование системы с целью оценить характеристики уровня производительности (временные, использование ресурсов, потенциальные возможности).

Временные - характеристики связанные с временем выполнения той или иной операции.
Использования ресурсов - 
Потенциальные возможности - запас мощности. 

Производительность в контексте WEB приложений

Система сервер + сеть + клиент
Со стороны сервера: физические характеристики (процессор, оперативная память и пр.)
Сеть: скорость, пропускная способность и пр.
ПО на сервере: ОС, сервер приложений, web сервер, БД, само приложение.
Клиент: клиентское ПО (браузер или др.)
Пример временной характеристики: время отклика на запрос от клиентского ПО на сервер.
Для одновременной работы с множеством пользователей нужны ресурсы (процессорное время для вычислений, оперативная память для хранения данных, пропускная способность сети) и запас ресурсов на случай наплыва пользователей.

Но в реально жизни пользователи не подключаются напрямую к серверу.

Вместо сервера, как правило, мы имеем дело со сложной распределенной (логически, физически, географически) системой.
Типичное современное WEB приложение требует наличие трёх основных компонентов: сервер БД, сервер приложений, WEB сервер.

Дальше сложнее.
Клиенты пользуются разными устройствами
Подключаются к сети Интернет через разных Интернет провайдеров. 

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

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

Что значит "быстро"?
меньше 0,1 секунды - "мгновенно", "моментально"
менье 1,25 секунды - "быстро"
менье 2 секунд - "достаточно быстро"
2-4 секунды - "приемлемо"
4-15 секунды - "медленно"
больше 15 секунд - "очень долго"

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


1.2 Основные строительные блоки тестов

Взаимодействие между браузером и сервером обычно происходит по протоколу http/https

Строительные блоки
Запрос - основной элемент
Транзакция - комплект запросов
Сценарий - логическая цепочка, длинная серия логических транзакций
Профиль нагрузки - сколько и каких сценариев нужно выполнять 

1.6 Пример создания простого сценария в JMeter
Среда разработки сценариев JMeter
Левая часть окна JMeter содержит сценарии в виде дерева
В правой части окна показываются свойства выбранного элемента
Элемент верхнего уровня называется Test Plan – это корневой элемент, все остальные элементы находятся внутри него.


Для того чтобы внутрь элемента добавить вложенный элемент можно кликнуть правой кнопкой по элементы и выбрать пункт меню Add или сделать тоже самое через меню 

Внутрь Test Plan добавляются группы потоков (Thread Group), затем внутрь группы потока добавляются элементы.
Каждая группа потоков содержит внутри себя некоторый набор элементов, который в совокупности представляет сценарий. И в рамках группы потоков этот сценарий выполняется параллельно, как будто его выполняет несколько пользователей.

При тестировании Web приложений ключевым элементов является HTTP Request/
Помимо запросов в группу потоков могут быть добавлены:
  • конфигурационные элементы, которые например подгружают тестовые данные;
  • элементы которые управляют потоком выполнения, например позволяет писать разветвляющийся сценарий;
  • проверки, которые контролируют действительно ли ответы от сервера удовлетворяют некоторым требованиям;
  • таймеры, т.е. вставлять некоторые задержки;
  • и т.д.

Запись сценария в JMeter происходит при помощи рекордера который встраивается как прокси  (т.е. посредник) между браузером и Web приложением.
Т.е. включаем рекордер - после этого в браузере выполняем необходимые действия - в результате этих действий отправляются запросы на Web сервер - JMeter эти запросы перехватывает и записывает в виде сценария, который можно будет запускать.

Соответственно чтобы настроить эту схему взаимодействия, нужно:
  1. запустить рекордер, который будет работать как прокси-сервер.
  2. в браузере изменить настройки прокси так, чтобы они указывали на JMeter.
Рекордер удобнее всего добавлять непосредственно в Test Plan на верхний уровень. Он находится в пункте меню Non-Test Elements и называется HTTP(S) Test Script Recorder.
В разделе свойств рекордера в поле Target Controller указать куда будут записывать все выполненные запросы.

Чтобы посмотреть какие запросы отправлялись и какие ответы присылал сервер можно в группу потоков (Thread Group) добавить элемент Listener - View Result Tree. Этот элемент будет содержать всю информацию обо всех выполненных запросах и обо всех полученных от сервера ответах. 

Чтобы сценарий мог работать с Cookie нужно подключить конфигурационный элемент HTTP Cookie Manager.

Для генерации нагрузки нужно указать сколько виртуальных пользователей в течении какого времени будут одновременно выполнять разработанный нами сценарий. Т.е. нужно описать профиль нагрузки. 
В JMeter это задается параметрами группы потоков (Thread Group):
Number of Thread (users) - количество пользователей, которые должны одновременно выполнять этот сценарий;
Loop count - количество итераций, сколько раз каждый пользователь должен выполнить этот сценарий
или можем поставить галочку Specify Thread lifetime и задать расписание:
Duration (seconds) - продолжительность работы пользователей, пользователя будут выполнять сценарий раз за разом пока время не истечет. 
Сколько итераций получилось можно посмотреть в отчете:
добавить элемент Listener - Summary Report

2. Сценарии

2.1. Параметры: конфигурации и данные

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

Параметры данных, тестовые данные - относятся к отдельному запросу, постоянно меняются. 

Комплект параметров конфигурации: Дефолтные настройки для запросов которые отправляет JMeter.

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

Для этого можно использовать следующий конфигурационный элемент:
HTTP Request Default.
При помощи него можно поменять параметры (протокол, адрес сервера, порт, кодировку и др.) в одном месте и изменение повлияет на все запросы сценария.
Важно: значения, которые будут указаны в HTTP Request Default будут использоваться в конкретном запросе только в том случае, когда соответствующее поле в нём пустое. Если не пустое, то используется то значение, которое в этом поле указано. 

После того как перенесли параметры в конфигурационный элемент HTTP Request Default - нужно удалить значения из всех запросов, чтобы использовались дефолтные значения, которые настраиваются сразу для всех запросов.
Но чтобы не удалять в каждом запросе по отдельности, можно удалить все имеющиеся запросы и записать сценарий ещё раз рекордером. При этом в сценарии у нас уже будет элемент HTTP Request Default. 
В этом случае рекордер не будет в запросах заполнять соответствующие поля если их значения совпадают с дефолтными.
Адрес сервера и прокси-сервер - это наиболее часто встречающиеся настройки для которых указываются дефолтные значения при помощи элемента HTTP Request Default.
Также на производительность могут сильно влиять параметры заголовка запроса (выбор языка, выбор механизма сжатия, user agent(браузер, мобильный или десктопный)).
Заголовки запроса находятся внутри запроса:


Accept-Language - указывает какой язык установлен в настройках браузера по умолчанию.
Cash-Control - сообщает выполнялся ли ранее такой запрос и лежит ли сохраненная версия ответов в кэше.
Accept-Encoding - допустимые алгоритмы сжатия поддерживаемые браузером.
User-Agent - указывает из какого браузера был отправлен запрос, в т.ч. мобильный или десктопный. https://useragentstring.com/

Чтобы параметризовать сценарий таким образом, чтобы можно было изменять параметр в одном единственном месте. Например, мы хотим чтобы все запросы отправлялись от какого-то другого браузера.
Можно взять элемент HTTP Header Manager из любого запроса и скопировать на верхний уровень, в группу потоков (Thread Group).
Чтобы не удалять в каждом запросе элемент с заголовками, можно перезаписать сценарий рекордером предварительно убрав галочку Capture HTTP Header
Но этот варианты не очень хорош, т.к. некоторые параметры заголовков должны быть разные у запросов.
Можно удалять отдельные заголовки, но есть решение лучше.

Глобальные переменные
Конфигурационный элемент User Defined Variables позволяет задавать значения для переменных.
После настройки этого элемента ещё раз перезапускаем рекорден, предварительно нужно обратно поставить галочку в поле Capture HTTP Header.
Есть путь ещё проще - переменные и значения в отдельном файле. Это можно сделать через компонент Variables from CSV File.

2.2. Тестовые данные

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

Самый простой способ избавиться от фиксированных тестовых данных, т.е. сделать так чтобы они на каждой итерации отличались - использовать счётчик.
Открываем запрос с методом POST с параметрами которые передаются в теле запроса и настраиваем, чтобы вместо фиксированных запросов передавались значения которые содержат некоторый счетчик.
Подстановка осуществляется через переменную, например ${COUNTER}
В группу потоков (Thread Group) добавляем конфигурационный элемент, который так и называется Counter. В нём нужно указать исходные значения (Starting value), насколько будет увеличиваться счётчик (Increment), максимальное значение, название переменной

Запускаем, получаем

Формат значения счётчика можно задать в конфигурационном элементе Counter поле Number format, например "000"

Получим

Если нужны более разнообразные тестовые данные, а значения из какого то набора и это набор может быть спроектирован по правилам тест-дизайна. Например включает в себя: короткие значения, короткие строки, длинные строки, средней длины строки, строки содержащие определенные символы и пр.
И удобнее всего хранить такой набор значений в отдельном файле.
Для чтения данных из внешнего файла в JMeter используется конфигурационный элемент CSV Data Set Config

Выбираем файл, задаем наименование переменных Variable Names, указываем разделитель Delimiter.

После чего в запросе c формой, которая содержит тестовые данные фиксированные значения меняем на переменные значения.

Есть и другие способы загрузки файла.

Но данные из файла и счётчик детерминированы, т.к. всё время одни и те же.
Если хотим добавить болье случайности в тестовые данные, например случайное число.
Для этого добавить в сценарий конфигурационный элемент Random Variable

Указываем название Variable Name, указываем формат Output format, минимальное и максимальное значения.

В запросе меняем имя переменной и получаем

Если нужно сгенерировать случайные строки то используем функцию ${__RandomString(5)}. Ознакомиться с функциями подробнее можно в инструкции  https://jmeter.apache.org/usermanual/functions.html
Подставляем функцию и получаем
непонятные символы.
Согласно инструкции можно указать символы которые могут генерироваться в строке: ${__RandomString(10,abcdefg)}
Получаем

Чтобы сделать разную длину строк вместо значения количества символов ставим функцию ${__Random(0,10)}.
Получаем функцию: ${__RandomString(${__Random(0,10)},abcdefg)}.

2.3 Корреляция запросов

Когда требуется вернуть идентификатор, например существующего пользователя или заказа, и этот идентификатор нельзя сгенерировать случайным образом, нельзя загрузить из файла, когда идентификатор необходимо получить из самого тестируемого приложения. Например для интернет-магазина мы должны отправить запрос, который вернет список заказов, т.е. ответ на этот запрос будет содержать идентификаторы заказов, из ответа идентификаторы (или др. данные) нужно извлечь и поместить в переменную. Которую потом можно будет использовать в следующем запросе, подставив туда её значение через конструкцию ${ ... }.

Пример:
Для модификации/редактирования текущих данных можно создать новую группу потоков (Thread Group) или дублировать действующую через copy/paste. 
Вместо запросов на создание данных (запрос на открытие формы для создания новых данных и запрос на отправку этих данных) - запрос на редактирование данных (запрос на открытие формы для редактирования существующих данных (заказа или аккаунта)).

Чтобы посмотреть, как этот запрос будет выглядеть, проделаем манипуляции через браузер.
В браузере открыть DevTools, перейти на вкладку Сеть (Network) - здесь будут показываться запросы, которые отправляет браузер.
Произведя манипуляции по изменению данных (нажать кнопку для изменения данных) мы увидим запрос и можем посмотреть параметры запроса. Такие же параметры нужно внести в запрос в JMeter (запрос на открытие формы для редактирования существующих данных (заказа или аккаунта)). Открываем запрос, который ранее был на открытие формы для создания новых данных, меняем параметры на те, которые указаны в браузере для изменения данных (запрос на открытие формы для редактирования существующих данных (заказа или аккаунта)).
Такую же процедуру проводим с запросом на изменение и отправку данных. Т.е. вносим изменения, отправляем или сохраняем эти изменения и смотрим параметры.

Может быть ситуация, когда идентификатор имеет простое происхождение (например номер по порядку). И при изменении параметров в запросе в JMeter мы прописали номер этого идентификатора. Но если удалят данные именно по этому идентификатору? В этом случае можно заменить значение идентификатора в параметрах запроса в JMeter на переменную. Например идентификатор можно получить, проанализировав ответ на предыдущий запрос, который, к примеру, возвращает страницу со списком заказов.
Для того чтобы, из ответа на этот запрос извлечь значение и поместить его в переменную используются так называемые экстракторы. Эти элементы в JMeter находится в разделе Post Procession (Post означает что они выполняются после запроса, Pre процессоры выполняются перед запросом). Компонент в названии содержат слово Extractor.
Для WEB приложения наиболее естественный это CSS Selector Extractor

Заполняем поля:
Name of created variable - название переменной, в которую должен быть посещен результат. И вместо фиксированного значения указываем подстановку значений этой переменной через конструкцию ${ ... }.
CSS Selector expression. CSS Selector - язык запросов для поиска информации на страницах WEB приложений. Здесь указываем какой элемент мы ищем, в квадратных скобках указываем дополнительные условия на этот элемент 
Attribute  - атрибут, который нужно получить.
Match No (0 for random) - номер соответствия.

Техника переноса данных из одного запроса в другой, точнее из ответа на предыдущий запрос в следующий зарос и называется корреляцией запросов.

Важные моменты: 
экстрактор должен находиться внутри того запроса, к которому он применяется, из ответа на который он должен извлекать информацию;
если при выполнении запроса автоматически происходит перенаправление (стоит галочка в запросе Follow Redirects), то в экстракторе нужно поставить галочку Main sample and sub-samples.

Полезный приём отладки сценариев, который позволяет более наглядно просматривать значения переменных, которые извлекаются экстракторами. Для этого нужно добавить в сценарий компонент, который называется Debug Sampler. Лучше всего добавить его в то место сценария, в котором нужно узнать значения переменных.
Debug Sampler используется исключительно для отладки в частности для того чтобы просматривать значения переменных. Их можно будет увидеть в элементе View Results Tree- там будет отображен Debug Sampler в котором на вкладке Response Data можно увидеть значения переменных 

2.4 Проверки (assertions)


Что можно проверять:

Код ответа
Код ответа, который присылает сервер. В стандарте http есть несколько серия кодов ответа. 200 и 300 серии считаются успешными, 400 и 500 - ошибочные ответы. 
Отслеживать ошибки статус по кодам ответа можно через элемент Listener - View Result Tree и элемент Listener - Summary Report.

Таймауты
Способы установить таймаут для запроса:
1. Указывается в свойствах самого запроса

2. Использование элемента Duration Assertion

Разница между ними в том, что в первом случае если нарушается таймаут - соединение прерывается и не будут получены ответы от сервера.
А во втором случае ответы будут получены, при этом будет сообщение, что в предполагаемое время не уложились.

Размеры ответа
Используется для:
1. Поиска больших страниц
2. Некоторые приложения в случае возникновения ошибки не возвращают код 400 или 500 серии, а возвращают код ответа 200. Но страница, которая при этом возвращается в браузер содержит какое-то сообщение об ошибке и если это сообщение об ошибке маленькое, т.к. оно заметно меньше чем нормальная страница, то можно поставить проверку, которая будет находить такие проблемные страницы по размеру.
Чтобы проверить размер добавляем элемент Size Assertion
можно указать какой должен быть размер или больше/меньше какого-то значения и можно это указать или для всего запроса, или для заголовка, или для тела

Содержимое ответа
Например если мы знаем, что страница с сообщениями об ошибках содержит какой-то характерный  текст, то можно для каждой страницы сделать такую проверку. 
Выполняется при помощи элемента Response Assertion. 
Он может проверять не только текст, но и код ответа, заголовки, проверять наличие или отсутствие текста, а также можно использовать регулярные выражения.

Чтобы уменьшить вероятность ложных срабатываний, лучше проверять не наличие какого-то текста, а наличие элемента с заданным идентификатором. 

Для этого используется элемент XPath Assertion.

Используя компонент XPath Assertion можно проверить наличие элемента по заданному XPath запросу. Если страница не удовлетворяет стандартам XML, тогда нужно поставить галочку Use Tidy (tolerant parser).
XPath (XML Path Language) — язык запросов к элементам XML-документа.

Есть ещё вариант уменьшения ложных срабатываний при проверке текста при помощи Response Assertion: на странице найти блок текста, который можно как-то идентифицировать и внутри которого необходимо искать требуемый текст.
Для того чтобы это реализовать в JMeter необходимо построить комбинацию из экстрактора и проверки.
Добавляем сначала экстрактор CSS Selector Extractor. Ставим экстрактор перед проверкой Response Assertion. Проверку активируем и указываем в поле "JMeter Variable Name to use", что она должна применяться не к самому телу, а к переменной, которая построена при помощи экстрактора. 

Если хотим проверить что-то сложное, провести какую-то функциональную проверку, например проверить верно ли суммировались данные, то здесь помогут компоненты, которые позволяют написать произвольный код на языке программирования и там можно проверять всё что угодно. 
Вот эти компоненты: BeanShell Assertion, JSR223 Assertion. 
Они позволяют писать код на разных языках программирования.

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

2.5 Управление потоком выполнения


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

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

Все элементы, которые управляют потоком выполнения находятся в разделе Logic Controller.

Первый прием для усложнения - выполнение некоторых действий один раз в начале сценария.
Для этого используется элемент Once Only Controller. То что находится внутри него выполняется один единственный раз. Этот элемент не обязательно должен находится в начале сценария.
Необходимый запрос добавляем внутрь этого блока Once Only Controller

Следующий прием  многократное повторение какого-то действия. Понятно, что сценарий сам выполняется несколько раз подряд, здесь речь идет не о сценарии целиком, а об одном отдельно взятом действии или нескольких подряд идущих действиях, которые нужно выполнить многократно и только после двигаться по сценарию дальше. 
Используется элемент Loop Controller, указываем количество повторений.
Он подходит если точно известно, сколько раз нужно выполнить элемент.

Если нужно повторять действие до того момента, пока его можно выполнить (например удаление товаров из корзины), то выбираем элемент While Controller. Он будет выполняться до тех пор, пока переменная которая указана в поле Condition имеет значение отличное от fault/false. При этом в экстракторе в поле Default Value указать значение fault/false.
Этот элемент управления удобен тогда, когда условие формулируется: выполнять до тех пор, пока что-то не случится. Либо извлечь необходимую информацию из предыдущих запросов.
Для того, чтобы JMeter извлёк не один элемент при помощи экстрактора, а сразу все нужно указать в экстракторе CSS Selector Extractor в поле Match No (0 for random) "-1" - означает что интересуют все значения.
Элемент отладки Debug Sampler - просто показывает значения переменных. В этом списке переменных можно найти переменную, которая указывает количество элементов в списке.
Чтобы обработать все элемент этого списка можно использовать элемент управления ForEach Controller.

В поле Input variable perfix указать префикс переменной и задать новое имя в поле Output variable name.
И в запросе проставляется имя из поля Output variable name и тогда запускается цикл и последовательный перебор.

Следующий прием управления потоком выполнения - это проверка некоторых условий (то ли да, то ли нет).
Например, сценарий выполняется много раз, на первой итерации выполняется Login, потом несколько раз сценарий проходит в рамках той же самой сессии на, например, 10 итерации выполняется Logout, потом на 11 итерации снова выполняется Login и т.д. по циклу.
Для этого в группу потоков добавляется счетчик Counter и указать что он должен начинаться от 0 и, например, до 9 с шагом 1 и ставим галочку Track counter independently for each user.
После чего меняем  Once Only Controller на If Controller, который проверяет значение переменной, и на Logout тоже добавляем If Controller (точнее добавляем запрос внутрь элемента).

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

Например, повторяющиеся действия в интернет-магазине - открываем категорию товара, выбираем какой-то товар, добавляем в корзину - просто с разными вариациями. 
Добавим новую группу потоков и сделаем её неактивной, и переименуем в Module Library (Библиотека модулей). Эта группа потоков выполняться не будет, в ней просто будет храниться какие-то фрагменты которые можно использовать в основной группе потоков.
Создаем элемент Simple Controller и внутрь помещаем необходимый фрагмент. Но второй раз нам необходимо будет выполнять его с модификациями, поэтому нужно сделать это блок параметризованным. В JMeter встроенных возможностей для этого нет, зато есть дополнительный плагин который называется Parameterized Controller.

Добавляем в основную группу потоков Parameterized Controller. Внутрь него добавляем Module Controller, который будет ссылаться на Simple Controller который находится в Библиотеке модулей. 
Теперь определим какие параметры туда должны передаваться. Вводим переменную, которой передается та часть, которая действительно меняется - в примере это идентификатор товара.
В элементе Parameterized Controller указываем значение этих переменных. После чего удаляем уже не нужные запросы и делаем дубль Parameterized Controller+Module Controller и вводим другие необходимые параметры.

2.6 Протоколы взаимодействия

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

Если речь идёт о WEB приложениях, то самым распространенным является протокол http(s)

Есть ещё протокол взаимодействия WebSoket - этот  протокол, в отличии от http(s) обеспечивает более тесное и более быстрое взаимодействие браузера и сервера и используется для создания более интерактивных приложений. В базовой комплектации JMeter этот протокол не  поддерживается, но через менеджер плагинов можно установить дополнительный компонент, который позволит взаимодействовать по этому протоколу. 

Распространенная технология Remote API (SOAP, REST) - удаленные программные интерфейсы.
Для работы с SOAP в JMeter есть специальный компонент. Для работы в REST он не нужен, т.к. используется тот же самый инструмент, который используется для работы с http(s) запросом HTTP Request. С помощью HTTP Request в ответ на запрос можно получить текст в формате JSON.
В есть JMeter специальный экстрактор, который позволяет анализировать текст формата JSON и извлекать из него необходимую информацию JSON Extractor и JSON JMESPath Extractor.

В JMeter есть возможность прямого взаимодействия с БД по протоколам ODBC и JDBC. Нужно это например для извлечения информации из БД и использования в качестве тестовых данных. 
С помощью JMeter можно тестировать БД напрямую - выполнять запросы, замерять скорость выполнения этих запросов, обращаться к хранимым данным.

Протоколы почты SMTP, POP3, IMAP. Нужно учитывать что почтовые протоколы очень медленные. 

Использование библиотеки Selenium Web Driver - работать в браузере. 

Есть возможность работать на уровне протоколов TCP, UDP.

Или Java API для работы с библиотеками. 

А ещё можно писать свои инструменты.


3.1 Как формулировать требования к производительности 


 
Стандарт 25000.
Раздел производительности - в эту группу включают всё что связано с временем, использованием ресурсов и потенциальной возможностью системы/запас мощности.
Также при тестировании производительности под большой нагрузкой, часто параллельно оценивается надежность 
Надежность - отказоустойчивость, восстанавливаемость, готовность.
Готовность иногда на русский язык переводят как доступность
Availability - это время в течении которого система работает и к ней можно получить доступ и воспользоваться её функциями.
Если смотреть с точки зрения конечного пользователя то ему время отклика на отдельные запросы не так интересны, ему важно общее время выполнения операции, за какое время он сможет, например, оформить заказ в web-магазине или сформировать какой-то отчёт с учётом всех предварительных действий - сколько ему нужно будет заполнить форм, каких, насколько удобно это всё организовано. Здесь мы вторгаемся в другую область качества - удобство использования. 
Конечный пользователь, как человек, как правило не очень хорошо разделяет, где заканчивается удобство использования и начинается собственно производительность системы.

Показатели используемые при описании производительности:
время отклика (response time)
пропускная способность (throughput) - количество событий, которые произошли за единицу времени
способность к распараллеливанию (concurrency)
готовность (availability, uptime)
потребление ресурсов (resource utilization)
потенциальная мощность (capacity)

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

3.2 Цели тестирования и профили нагрузки






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

Виды тестирования производительности:
Это названия для типовых профилей нагрузки, которые часто используются при тестировании производительности. 

Нагрузочное тестирование - это тестирование при постоянной нагрузке, но ниже предельной. 
Признаком этого вида тестирования производительности является использование профиля, в котором количество транзакций сохраняется в течении длительного времени, оно является постоянным. Количество виртуальных пользователей тоже может оставаться постоянным.

Стрессовое тестирование - непрерывно возрастающая нагрузка. Увеличивающееся количество сценариев или увеличивающееся транзакций. 
Целью этого вида тестирования является доведение системы до состояния и зафиксировать, когда начинают появляться проблемы или изменяется поведение системы.  Это так называемая точка насыщения.

Спайк-тестирование (пиковая нагрузка)
Тестирование с нагрузкой выше предельной на короткое время, т.н. пики.


3.3 Реализация профилей нагрузке в JMeter

Нагрузочное тестирование

Чтобы создать постоянную нагрузку нужно использовать простой компонент который описывает группу потоков. 
Необходимо задать время для разогрева сервера в поле Ramp-up period (seconds).
Для использования задержки в JMeter используют элементы группы Timer. Есть простые таймеры которые предоставляют фиксированную задержку или случайную задержку. 
Есть таймер Constant Throughput Timer который автоматически подбирает задержку таким образом чтобы обеспечить заданную пропускную способность - количество запросов в единицу времени. Поле Target throughput (in sample per minute). Также можно через выпадающее меню Calculate Throughput based on выбрать, чтобы учитывались только запросы, которые выполняются в одной группе потоков одним виртуальным пользователем или всеми виртуальными пользователями вместе и пр. 

Стрессовое тестирование. 
Создать непрерывно возрастающую нагрузку можно несколькими разными способами. 
1. Например просто в группе потоков (Thread Group) указать большое количество пользователей в поле Number of Thread (users) и большой период для разгона сервера в поле Ramp-up period (seconds) поставить галочку количества итераций на бесконечность Loop count - Infinite.
и указать общее время выполнения теста в поле Duration (seconds) не менее времени указанного в поле Ramp-up period (seconds).
Для отслеживания добавим элемент jp@gc - Active Threads Over Time. Его нет в базовой комплектации, для того чтобы он появился, нужно через менеджер плагинов добавить модуль "3 Basic Graphs".

2. Использование специальной группы потоков  jp@gc - Stepping Thread Group. Его тоже нет в базовой комплектации, для того чтобы он появился, нужно через менеджер плагинов добавить модуль "Custom Thread Group".
С технической т.з. в элементе  jp@gc - Stepping Thread Group описывается тоже самое:
сколько должно быть запущено потоков всего в поле This group will start, как быстро должно нарастать количество потоков и сколько всего времени нужно будет выполнять этот тест (поле Finally, stop).


3. Использование специальной группы потоков bzm - Concurrency Thread Group. Примерно тоже самое, что и предыдущий компонент.

4. Использование специальной группы потоков bzm - Arrivals Thread Group. 
Здесь подход немного другой. Инструмент считает, сколько сценариев успевает завершиться за единицу времени. Главное отличие этого способа в том, что нагрузка (количество сценариев и количество запросов) будет возрастать нелинейно. Т.е. этот компонент подстраивается под время выполнения запроса. 

Спайк-тестирование (пиковая нагрузка)
Тестирование с нагрузкой выше предельной на короткое время, т.н. пики.
1. Использование специальной группы потоков jp@gc - Ultimate Thread Group.
Эта группа потоков предназначена чтобы настраивать сложный профиль нагрузки. Описание профиля нагрузки состоит из участков (строк, Row).
2. Через обычные группы потоков. Сначала настроить группу потоков, которая будет обеспечивать базовую нагрузку. После чего делаем вторую группу потоков, которая будет выдавать пиковые нагрузки. Чтобы они возникали периодически - во вторую группу потоков добавить таймер задержки. 

3.4 Задержки, зачем они нужны

Правила использования таймеров в JMeter
1. Таймер действует на все запросы, которые находятся в текущем контексте. Т.е. на все запросы, которые находятся внутри того элемента, который содержит этот таймер.
2. Таймер срабатывает перед запросом, а не после него. Т.е. если необходимо запустить таймер после запроса, то его необходимо поместить в специальный элемент Flow Control Action
который необходимо разместить после нужного запроса. А в поле Duration (milliseconds) указать значение 0.
Элемент Flow Control Action можно разместить между запросами или между транзакциями.

Для работы с КЭШ есть специальный конфигурационный элемент HTTP Cache Manager. Он будет отправлять запросы с учетом срока годности кэша, эмулируя работу браузера.

3.5 Подготовка к запуску и запуск тестов. Алгоритм действий.
Запуск тестов. Первые шаги.

3.6 Ручное тестирование производительности

Целью этого вида тестирования является оценка скорости загрузки одной отдельно взятой страницы. 
В DevTools во вкладке Network можно увидеть подробную информацию о том, какие запросы отправляются и сколько на это тратится времени. 
Также для анализа можно использовать инструмент Lighthouse в DevTools
Также можно использовать онлайн сервисы для анализа производительности страниц.

Можно использовать этот инструмент под нагрузкой и без неё.

4.1 Анализ результатов в JMeter

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

Возникает вопрос - как сохранить?
Для этой цели используется компонент Simple Data Writer
в поле Filename указывается файл, который должны сохранится данные и настройки Configure, которые определяют формат файла и то, какие именно показатели сохраняются.

Помимо сохранения результатов, нужно следить за тем, что происходит в режиме реального времени, а именно следить за тем, нет ли катастрофических ошибок, после которых можно тестирование не продолжать.
Для этого используется компонент Summary Report
и особенно внимательно следить за столбцом Error % который показывает процент отказов, сбоев во время выполнения тестов. 

И конечно нужно следить за показателями производительности в реальном времени при поиске точек насыщения. Некоторые точки насыщения тоже можно заметить по появлению сбоев, отказов, когда значение в колонке Error % начинает отличаться от 0. Но бывают и другие точки насыщения, когда, например, время отклика или пропускная способность начинают резко возрастать.

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

Для визуализации результатов используют графики. Для их построения используют различные компоненты. Но во время проведения тестов лучше их отключить, данные в графопостроитель можно загрузить позже, из файла, в который они были сохранены компонентом Simple Data Writer.
Graph Results
jp@gc - Response Times Over Time
jp@gc - Transactions per Second

4.2 Сравнительный анализ результатов
Как сравнивать время отклика для разных запросов разбирали в предыдущей главе (через графопостроители).

Время отклика и пропускная способность.
Можно сравнивать время отклика и пропускную способность. Несмотря на то, что это два совершенно разных графика и показатели имеют разные единицы измерения (время отклика - секунды ли миллисекунды, пропускная способность - транзакции в единицу времени или байты в единицу времени). Но эти два графика удобно нарисовать вместе рядом, для того чтобы смотреть зависимость времени отклика и пропускной способности от текущего времени, от продолжительности выполнения тестов, и как следствие от текущей нагрузки. Потому что мы знаем какая нагрузка подается на систему в каждый момент времени. 
Глядя на эти оба графика мы можем заметить, что именно в тот момент, когда есть точка насыщения и изменения поведения на графике времени отклика, в то же самое время происходят какие-то изменения и на графике пропускной способности. Или наоборот не происходит. И благодаря этой дополнительной информации мы можем делать какие-то дополнительные предположения, гипотезы относительно того, почему система себя так ведёт. 

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

Время отклика и latency (время до получения первого байта, время ожидания ответа)
Два показателя хорошо коррелируют между собой и измеряются в одинаковых единицах. 
Время отклика включает в себя и latency, и время получения данных.
Если видно что время отклика растёт, а время ожидания остается маленьким - это означает что растёт время загрузки данных, возможно что это связано с тем, что увеличивается размер ответа. Хорошо бы посмотреть одновременно три графика: время отклика, latency и размер ответа.
Другая ситуация: latency растёт также быстро, как и время отклика, а время получения данных по прежнему остается маленьким - значит запросы очень долго стоят в очереди, зато потом очень быстро обслуживаются. 

В JMeter можно рисовать график времен отклика для разных запросов при помощи компонента jp@gc - Response Times Over Time

При помощи менеджера плагинов можно установить плагин KPI vs KPI Graphs. Он позволит сравнивать количество хитов (пропускная способность в транзакциях в секунду) с текущей нагрузкой или среднее время отклика тоже с текущей нагрузкой.

Иногда нужно посмотреть время отклика для разных запусков. Например для двух разных профилей нагрузки. Можно загрузить два файла в jp@gc - Response Times Over Time. Но это не очень удобно.
Есть разные варианты, как можно построить графики
самый оптимальный RapidMiner


4.3 Анализ использования ресурсов

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

Можно начать с того, как расходуется процессорное время и оперативная память.

Инструменты для сбора информации:
  • для Windows используется инструмент perfmon
  • для Unix систем - sysstat (sar)
  • Специализированные - чтобы посмотреть как расходуются ресурсы внутри конкретного приложения, чаще всего они создаются вендором
  • Универсальные - Zabbix, Nagios - для мониторинга сложной сети 


4.4 Тестовый стенд и достоверность результатов. Подготовка тестового стенда.



"Реальный" тестовый стенд
Аппаратная конфигурация - такие же сервера, такой же мощности, с таким же количеством процессоров, количеством ядер, оперативной памяти, хотя бы один.
Конфигурация сети должна быть такая же, которая используется для реальных серверов. Например арендовать сервер в том же дата центре.
Реализовать такую же схему развертывания, как у реальной системы, такой же балансировщик нагрузки, также настроен. Если в реальной системе есть несколько серверов баз данных и между ними настроена репликация, попросить сделать хоты бы две базы, которые будут реплицироваться между собой.
Настройки тестового стенда должны быть такие же, какие используются для промышленной эксплуатации. Особенно механизмы кэширования.
Размер базы данных - скопировать существующую. 

Дополнительные факторы: тоже вносят вклад в производительность - инструменты
Генераторы нагрузки - потребляют ресурсы, нельзя размещать на той же самой машине, где находится тестируемая система.
Системы мониторинга - не должно быть слишком много, только то что необходимо и настолько редко, насколько это возможно.
Дополнительный трафик - отделить или собирать локально, но тогда появляется нагрузка для системы ввода-вывода. Или выделить отдельный жесткий диск для сохранения данных.
Фоновые процессы 
    
4.5 Распределенная генерация нагрузки - генерация нагрузки из нескольких точек


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

4.6 Понятные отчеты. Рекомендации по написанию отчетов







Комментариев нет:

Отправить комментарий