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

Вячеслав Смирнов

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

Вячеслав Смирнов

owasp@yandex.ru

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

Что такое
тестирование производительности?

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

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

    Инженер по производительности —
    на все руки мастер

    Задача:
    провести тестирование производительности

    Тестирование производительности
    • подсистем серверов
    • серверов и приложений на простых запросах
    • приложений при выполнении сценариев
    • в соотвествие с требованиями

      Задача:
      провести тестирование производительности
      подсистем серверов

      Смоделировать нагрузку на: диск

      Смоделировать нагрузку на: диск

      fio — Flexible I/O Tester (github.com/axboe/fio)

      Рекомендуется Amazone EC2, Google Cloud, Alibaba Cloud:

      Смоделировать нагрузку на: диск

      fio — Flexible I/O Tester (github.com/axboe/fio)

      Смоделировать нагрузку на: процессор

      Смоделировать нагрузку на: процессор

      Phoronixphoronix-test-suite.com

      			phoronix-test-suite benchmark smallpt
      			    Test Results:
              57.683207988739
              57.237819910049
              57.684161901474
          Average: 57.54 Seconds
      		

      Смоделировать нагрузку на: сеть

      Смоделировать нагрузку на: сеть

      Смоделировать нагрузку на: сеть

      iperf3software.es.net/iperf/

      			iperf3 -s
      			iperf3 -c 192.168.1.66
      [ ID] Interval           Transfer     Bandwidth       Retr
      [  4]   0.00-10.00  sec  42.9 GBytes  36.8 Gbits/sec    0             sender
      [  4]   0.00-10.00  sec  42.9 GBytes  36.8 Gbits/sec                  receiver
      		

      Узконаправленная синтетическая нагрузка

      1. Смоделировать нагрузку на подсистемы:

      Задача:
      провести тестирование производительности
      серверов и приложений на простых запросах

      Подать нагрузку на: балансировщик

      Подать нагрузку на: сервер баз данных

      Подать нагрузку на: сервер приложений

      Подать нагрузку на: сервер приложений

      Подать нагрузку на: сервер приложений

      Статичные несвязанные запросы к системе

      1. Подать простую эталонную нагрузку на сервисы:
        • балансировщик — httperf, ab
        • сервер баз данных — sysbench, pgbench
        • сервер приложений — curl, wget, tcpreplay, ab

      Задача:
      провести тестирование производительности
      приложений при выполнении сценариев

      Часто и быстро выполнить сценарий

      Динамичные связанные запросы к системе

      1. Часто и быстро выполнить сценарий:
        • написать утилиту — "бешеный пользователь"
        • скомпоновать автотесты — повторить N раз

      Задача:
      провести тестирование производительности
      в соотвествие с требованиями

      Проверка на соотвествие требованиям

      Точная нагрузка по требованиям

      Инструмент подбирается под задачу

      Какую нагрузку подать?
      Обилие терминов в сети Интернет

      Виды
      тестирования производительности

      Видов тестирования много

      Виды тестирования производительности @polarnik (github.com)

      Выделим

      Виды тестирования производительности @polarnik (github.com)

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

      Производительность (performance)

      количественная характеристика
      скорости выполнения операций

      Выдержит ли система планируемую нагрузку?
      Есть ли узкие места?

      Нагрузочное тестирование (load testing)
      выполнение программы с повышением нагрузки
      от среднего профиля до максимального и выше

      Нагрузка подаётся ступенями

      растёт количество операций в единицу времени

      Или нагрузка растёт плавно

      выше максимума, чтобы знать есть ли запас

      Анализ длительности обработки запросов

      ищём точку деградации и недоступности (timeout, 504, …)

      Сохраняем интенсивность (deg, off)

      сравниваем с профилем нагрузки (min, med, max)

      Анализ утилизации ресурсов: cpu, memory, …

      ищём узкое место, лимиты, в т.ч. конфигурационные

      Детальный анализ утилизации ресурсов

      необходимо понимание работы системы: %usr, %sys, …

      Анализ логов, ошибок, кодов ответов

      ищем точку появления ошибок под нагрузкой

      Сохраняем интенсивность (error)

      стараемся избавиться от ошибок и предупреждений

      Отчёт: точка деградации, ошибок, отказа, …

      и их отношение к профилю нагрузки: med, max

      Выбирем профиль для теста стабильности

      обычно, 80% от точки деградации/появления ошибок

      Нагрузочное тестирование (Load testing)
      ☑ Выдержит ли система планируемую нагрузку?
      ☑ Есть ли узкие места?
      Нашли точку деградации, ошибок, отказа
      выбрали максимальную рабочую нагрузку - work
      выявили узкие места и ошибки, устранили их

      Что будет при эксплуатации 24x7?
      Стабильна ли система под нагрузкой?
      Как быстро растёт размер базы данных и логов?
      Есть ли утечка соединений, памяти?
      Нет ли потерь данных?

      Тестирование стабильности (stability testing)
      длительное тестирование со средней нагрузкой, поиском отклонений и проверками корректности работы

      Выбирается рабочая нагрузка

      не выше предельной, чтобы не было ошибок

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

      всю ночь или все выходные

      Количественные и функциональные проверки

      выполняются во время или между итерациями

      Утечки ресурсов и ошибки

      попадут в отчёт по тестированию стабильности

      ☑ Что будет при эксплуатации 24x7?
      ☑ Стабильна ли система под нагрузкой?
      ☑ Как быстро растёт размер базы данных?
      ☑ Есть ли утечка соединений, памяти?
      ☑ Нет ли потерь данных?

      Если нагрузка ненадолго превысит максимум?
      Освобождаются ли неиспользуемые ресурсы?
      Восстановится ли система после ошибок?
      Какие ошибки проявляются под нагрузкой?

      Жил да был один сервер,
      было у него три друга-сервера,
      и однажды он решил перезагрузиться.

      Сначала всё было хорошо

      нагрузка на каждый сервер была средней

      Один ушел на перезагрузку

      нагрузка подросла

      Второй не выдержал

      нагрузка ещё подросла

      Третий не выдержал

      и снова нагрузка подросла, пользователи заметили

      Система начала восстанавливаться

      а нагрузка выравниваться

      Система почти восстановилась

      нагрузка распределилась

      Система справилась

      нагрузка снова минимальная

      Стрессовое тестирование (stress testing)
      тестирование за пределами рабочих нагрузок,
      в ограниченных ресурсах

      Быстро и ненадолго повысим нагрузку

      и повторим такой процесс несколько раз

      Выявим утечку ресурсов

      проверим корректность обработки исключений

      Выявим утечку ресурсов

      возможно, что ресурсы не освобождаются полностью

      Выявим утечку ресурсов

      возможно, что ресурсы не освобождаются частично

      Проверим реакцию на временное зависание

      быстро ли разбираются внутренние очереди системы

      ☑ Если нагрузка ненадолго превысит максимум?
      ☑ Освобождаются ли неиспользуемые ресурсы?
      ☑ Восстановится ли система после ошибок?
      ☑ Какие ошибки проявляются под нагрузкой?

      А что будет через 5 лет работы?
      Или через 10 лет работы при том же профиле?
      Или если размер документов увеличить?
      Нужно объёмное тестирование

      Объемное тестирование (volume testing)
      тестирование при увеличении объемов данных

      Наполняем базу, запускаем нагрузку

      сценарий — через 1 год работы

      Наполняем базу, запускаем нагрузку

      сценарий — через 5 лет работы

      Наполняем базу, запускаем нагрузку

      сценарий — через 10 лет работы

      Увеличивается объём БД, а не интенсивность.
      Нужно иметь и генератор нагрузки и данных.
      Быстрые генераторы БД пишутся на SQL.
      А готовят запросы на python, bash, java, …

      Обработка пакета запросов

      профиль нагрузки — размер пакета данных

      ☑ А что будет через 5 лет работы?
      ☑ Или через 10 лет работы при том же профиле?
      ☑ Или если размер документов увеличить?
      Объёмное тестирование проведено.

      Поможет ли увеличение памяти в 2 раза?
      Какой предел на другом железе?
      Какая производительность при двух серверах?

      Масштабируемости (scalability testing)
      серия нагрузочных тестов
      для разных профилей оборудования,
      количества серверов или узлов системы,
      настроек — размеров очередей, лимитов, …

      Наращивание мощности оборудования

      вертикальное масштабирование

      Тестирование на разных конфигурациях

      для прогноза затрат

      Наращивание мощности оборудования

      имеет технический предел

      Наращивание количества узлов

      горизонтальное масштабирование

      Наращивание количества узлов

      закладывается в архитектуру

      Наращивание количества узлов

      даёт гибкость

      ☑ Поможет ли увеличение памяти в 2 раза?
      ☑ Какой предел на другом железе?
      ☑ Какая производительность при двух серверах?

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

      Основа генератора пишется на SQL
      А Java/Scala/Python/Lua/Go/... лишь помогают

      SQL для генерации данных

      Почему SQL, а не API: Java/Scala/Python/C#/...

      Опыт использования SQL-генераторов

      Планирование данных

      Продумать шаблоны и количество

      Сценарий Шаблоны Количество
      Login_logout loadUser{N}@ok.org Users – 100к, History – x3
      Try_fail_pass incorrect{N}pass@bad.org Users – 50к, History – x1
      Reset_password user{N}Reset@password.com Users – 10к, History – x5

      Шаблоны

      Параметризация

      Шаблоны

      Параметризация

      Шаблоны

      Параметризация

      Подходы для генерации значений

      Объект – функция от параметров и номера

      			FOR index IN "indexStart".."indexEnd" LOOP
      			    value = function(index, params)
      			        Использование value для вставки в таблицы
      		

      Подходы для генерации значений

      [0; N-1] = Остаток от деления на N

      			value = index % 80000
      			
      		
      Получится:
      			77777
      			123
      			999999999
      		

      Подходы для генерации значений

      Функция format для шаблонных строк

      			nick_name = format('user %s name',
      			            index::text)
      		
      Получится:
      			user 77777 name
      			user 123 name
      		

      Подходы для генерации значений

      Комбинации format и остатка от деления для IPv4

      			format('106.%s.%s.%s',
      			       (((ip_index / 250) / 250) % 250)::text,
      			       (( ip_index / 250) % 250)::text,
      			       (  ip_index % 250 + 1)::text  )
      		
      Получится 15 625 000 значений:
      			106.0.1.2
      		

      Подходы для генерации значений

      GUID = md5 от имени таблицы, теста и номера

      			guid = md5( 'users '  ||
      			       test_name ||
      			       lpad(index::text, 12, '0'))::uuid;
      		
      Получится GUID для теста test_name:
      			faf154aa-54d1-0b07-3c8e-fe8921f96c45
      		

      Подходы для генерации значений

      GUID = md5 от имени таблицы, теста и номера

      Номер = 0 .. 999 999 999 999

      			guid = ('22-33-44-55' || 'aa-bb-cc-dd-ee-ff' || 
      			       lpad(index::text, 12, '0'))::uuid;
      		
      Получится GUID:
      			22334455-aabb-ccdd-eeff-000000000001
      		

      Подходы для генерации значений

      Выбор из словаря

      			array[ 1 + 
      			       mod(abs( index ), 
      			       arrayLenght) ]
      		
      предел 1 ГБайт

      Генерация тестовых данных: pandas, elizabeth

      Просто создать

      Person (жен)

      Не очень сложно сгенерировать

      отчество

      Дополнительно нужна

      транслитерация

      Удаление дублей

      Pandas

      Генерация серий

      Python

      Java, Scala когда важно не ошибиться

      Ставка на качественные данные

      Основа генератора пишется на SQL
      А Java/Scala/Python/Lua/Go/... лишь помогают
      Для спец. форматов используются библиотеки
      Для простоты используем сериализацию
      Затраты на генерацию окупаются стабильностью

      Вячеслав Смирнов

      owasp@yandex.ru,
      @qa_load

      Спасибо!