testengineer.ru

Домой Обучение Автоматизированное тестирование Тестирование производительности веб-сервисов - теория и инструменты

Тестирование производительности веб-сервисов — теория и инструменты

Автор

Дата

Категория

Разбираем, что это такое, аспекты, которые необходимо учитывать, и инструменты, которые вы можете использовать.

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

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

Какие аспекты производительности нас интересуют?

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

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

Стабильность: Нормально ли ведет себя система? Для оценки стабильности вы можете отслеживать количество ошибок.

Масштабируемость: Какие ресурсы нам нужно увеличить и сколько это будет нам стоить, если количество пользователей нашего сервиса удвоится? Станет больше в 10 раз? Для оценки масштабируемости вы должны анализировать использование ресурсов под разными нагрузками.

Что может быть узким местом?

При поиске «узких мест» в производительности веб-сервисов, мы бы обратили внимание на следующие моменты:

Нагрузка на базу данных: Является ли количество запросов, которые мы посылаем к базе данных, разумным? Быстро ли выполняются сами запросы?

Пиковое использование памяти: Есть ли что-то тяжелое, что вам нужно вычислить? Как это масштабируется? И масштабируется ли вообще?

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

Процессор: Когда загрузка процессора слишком высока, ваше приложение развалится на части 💥

Место на жестком диске: Лог-файлы и другие файлы, которые генерируются во время работы приложения, при длительной работе могут занять все место на жестком диске.

Соединения: Может существовать максимальное количество HTTP-коннектов/коннектов с БД. Для Postgres max_connections составляет 100. Рабочие nginx обычно ограничены 500 одновременными соединениями (источник).

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

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

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

Цель нагрузочного тестирования — увидеть поведение тестируемой системы под ожидаемой нагрузкой. Здесь нет необходимости сломать систему, цель тестирования — получить нагрузку, которую приложение ожидаемо будет получать в «часы пик». Способно ли приложение стабильно работать при ожидаемой нагрузке?

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

Стресс-тестирование

После нагрузочного тестирования мы узнаём, как система ведет себя при ожидаемой нагрузке. Цель стресс-тестирования — сломать систему. Когда приложение тестируется под экстремальной нагрузкой, чтобы увидеть, когда/где/как все ломается, это называется стресс-тестированием.

Стабильна ли система под нагрузкой? Видят ли пользователи сбои? Где верхний предел нагрузки? Восстанавливается ли система после сбоя? Когда происходит сбой, затрагивается ли только доступность системы или сбой влияет на корректность ее работы?

Тестирование стабильности (Soak testing)

Тестирование стабильности — это попытка ответить на вопрос, как система работает в течение длительного времени. Цель — подтвердить, что система надежна в течение длительного периода времени.

Вещи, которые могут пойти не так и быть обнаружены при таком тестировании:

  • Исчерпание соединений БД
  • Неожиданные перезагрузки сервера
  • Утечки ресурсов, например, утечки памяти
  • Журналы или другие файлы, которые раздувают систему

Профили нагрузки

Думайте о веб-сервисе в контексте тестирования производительности как о системе организации движения в городе. Люди хотят попасть из пункта А в пункт Б. Им нужно проехать через несколько улиц. Некоторые из них имеют 5 полос движения, другие — только одну. Одни позволяют двигаться со скоростью 130 км/ч, другие — 50 км/ч. В зависимости от времени может образоваться затор. Если есть узкое место, и машин немного, то, возможно, все будет работать как надо и заторов не будет. Но чем больше машин находится в дорожной системе, тем выше вероятность того, что кому-то придется ждать.

Дорожная система — это ваш веб-сервис. Узким местом может быть блокирующий вызов ресурса, например, транзакция базы данных при высоком уровне изоляции транзакций. Скорость движения — это скорость выполнения транзакции.

Инструменты нагрузочного тестирования

Существует масса инструментов для тестирования производительности и профилирования. Мы лишь кратко упомянем несколько, которые мы либо использовали в прошлом (Apache ab, Locust), либо хотим использовать (Apache JMeter, EatX, K6).

Apache JMeter

Apache JMeter — это инструмент нагрузочного тестирования на основе протокола. JMeter имитирует трафик и одновременных пользователей. Он похож на Locust, но работает быстрее.

Apache ab

Apache ab — это инструмент для бенчмаркинга HTTP-серверов. Как таковой, он охватывает гораздо меньшую часть вашей системы, чем Apache JMeter — только HTTP-сервер. Как правило, в большинстве случаев проблемы с производительностью скрыты не в HTTP-сервере.

Locust

Locust — это инструмент тестирования производительности, который позволяет вам определить веб-пользователей, отправляющих HTTP-запросы. Locust автоматически измеряет время отклика и отмечает пройденные/проваленные тесты. Для этого используется файл locustfile.py, который вы просто выполняете с помощью Python. Он выглядит следующим образом:

from locust import HttpUser, task, between
class QuickstartUser(HttpUser):
    wait_time = between(1, 2)
    def on_start(self):
        self.client.post(
            "/login",
            json={"username": "foo", "password": "bar"},
        )
    @task
    def hello_world(self):
        self.client.get("/hello")
        self.client.get("/world")
    @task(3)
    def view_item(self):
        for item_id in range(10):
            self.client.get(
                f"/item?id={item_id}", name="/item"
            )

Выполнение locust в папке с файлом locustfile.py запускает локальный веб-сервер, чтобы можно было взаимодействовать с Locust через браузер.

Locust

Первое, на что нужно обратить внимание — это статистика. Для каждой эндпоинта вы увидите количество запросов, которые были сделаны к этому эндпоинту. Locust измеряет количество неудачных запросов, время ответа и размер ответа. По времени ответа он показывает минимальное, медианное, среднее, 90%-квантиль и максимальное значения.

Locust результаты

На примере выше видно, что эндпоинт /users/registration падал несколько раз. У него также довольно высокое время отклика — как для максимального, так и для 90-процентного значения. Поскольку минимальное время отклика довольно низкое, это может быть индикатором того, что в работе этого конкретного эндпоинта есть узкое место.

Сейчас давайте посмотрим на ошибки:

Locust

Locust позволяет вам определять конкретные сообщения через response.failure('failure message') и показывает их здесь. Он также фиксирует более общие проблемы.

C помощью графиков можно определить точки отказа:

Locust графики

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

K6

K6 — это инструмент для нагрузочного тестирования. С помощью него можно писать тесты производительности на JavaScript. Вы можете записывать действия пользователей с помощью плагина Chrome и визуализировать результаты в Grafana. Он выглядит очень гибким, и мы собираемся использовать его на следующем проекте 😀

Углубляемся в проблемы производительности

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

Подсчет количества запросов

ORM — это замечательно, но очень легко можно столкнуться с проблемой (n+1)-го числа. Это довольно легко обнаружить, если написать модульные тесты для этих частей и также проверить количество выполненных SQL-запросов.

Изменение архитектуры микросервисов

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

Измерение использования памяти

Когда я работал над задачами в области машинного обучения, иногда случалось, что мне нужно было перемножать большие матрицы в продакшн-системе. Чтобы облегчить себе задачу, я измерял пиковое использование памяти с помощью valgrind и визуализировал его с помощью kcachegrind или memory_profiler в мире Python. Эти инструменты называются «профилировщики памяти», и они могут показать всевозможные вещи, включая графики вызовов, как на изображении ниже:

call-graph
Граф вызовов, построенный с помощью kcachegrind

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

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

Для поиска проблем с производительностью на фронтенде часто используют Google Lighthouse:

Обычно он запускается из инструментов разработчика Chrome, но вы можете интегрировать Lighthouse в ваш CI и запускать его автоматически при каждом билде!

Какое максимальное количество пользователей мы можем поддерживать?

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

Реалистичный сценарий: Похоже ли поведение виртуальных пользователей на поведение реальных?

Таймауты: Когда запрос считается медленным? Является ли время отклика в 3 секунды нормальным? Является ли нормальным время отклика в 300 секунд? Какие граничные значения скорости ответа?

Заключение

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

2 КОММЕНТАРИИ

ОСТАВЬТЕ ОТВЕТ

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

Последние публикации

Последние комментарии