Альтернатива Tsung и JMeter на базе Python для нагрузочного тестирования сервера

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

Прочитав эту статью, вы научитесь использовать этот инструмент нагрузочного тестирования. С его помощью можно получить представление о том, какое количество запросов в секунду (RPS) поддерживает ваш сервер. Согласно официальной документации, Locust — это:

«...простой в использовании распределенный инструмент, предназначенный для нагрузочного тестирования веб-сайтов (или других систем) и определения количества пользователей, с которыми одновременно может работать система».

Идея заключается в том, что во время тестирования сайт подвергается «атаке стаи саранчи» (от англ. locust — саранча). Поведение каждой саранчи (тестового пользователя) определяется вами, а процесс атаки отслеживается с помощью веб-интерфейса в режиме реального времени. Это помогает провести боевые испытания и выявить узкие места в коде, прежде чем допускать реальных пользователей.

Locust полностью основан на событиях, что позволяет поддерживать одновременно тысячи пользователей на одной машине. В отличие от многих других событийно-ориентированных приложений, в нем не используются callback-функции. Вместо этого он использует легковесные процессы через gevent. Каждая саранча, роящаяся на вашем сайте, фактически работает внутри собственного процесса (или гринлета, если быть точным). Это позволяет писать очень выразительные сценарии на Python, не усложняя код callback-функциями.

Это руководство состоит из четырех разделов:

  1. Установка

  2. Базовое использование

  3. Интерфейс командной строки

  4. Заключение

Давайте приступим!

1. Установка

Установка довольно проста, поскольку Locust поддерживается на 3.6, 3.7 и 3.8 (начиная с версии 0.14). Для установки достаточно выполнить соответствующую команду pip в зависимости от версии Python. Сначала настоятельно рекомендуется настроить виртуальную среду.

Обратите внимание, что locust был переименован из locustio в просто locust.

Python 3:

pip install locust

Последняя master ветка из git:

pip install -e git://github.com/locustio/locust.git@master#egg=locust

Приведенные выше шаги должны работать в Linux и Windows. Если что-то не работает, попробуйте следующий способ.

Дополнительный фикс для Windows

Во-первых, загрузите предварительно собранные бинарные пакеты для:

  • pyzmq

  • gevent

  • greenlet 

Для установки файла wheel (whl) выполните команду:

pip install name-of-the-package.whl

После этого просто запустите команду pip install.

pip install locust

MacOS

Для MacOS перед установкой pip нужно установить gevent. Самый простой способ — установить Homebrew:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Затем установите libev:

brew install libev

И, наконец, установите Locust с помощью pip install.

Проверка установки Locust

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

locust --help

Вы увидите следующий результат:

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

2. Базовое использование

Сервер Flask

Допустим, у вас есть файл с Flask сервером, myapp.py, готовый к нагрузочному тестированию:

from flask import Flask
server_port = 5000
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello, World!'
if __name__ == "__main__":
    app.run('0.0.0.0',port=server_port)

Просто запустите сервер с помощью кода в командной строке:

python myapp.py

Вы получите доступ к серверу через localhost:5000 и увидите вывод Hello World.

Скрипт Locust

Создайте новый файл с именем locustfile.py. Добавьте в него оператор import:

from locust import HttpUser, task, between

Продолжите написание класса, который наследует класс HttpUser. Класс можно назвать в соответствии со своими предпочтениями.

class WebsiteTestUser(HttpUser):

Внутри класса можно определить собственные функции, которые будут служить заданием для locust. По умолчанию он предоставляет два базовых класса, которые вызываются при старте и остановке вызова Locust:

  • on_start

  • on_stop

Если поверх функции добавить декоратор @task, то она будет рассматриваться как задача для Locust. В следующем примере показана простая задача, тестирующая API localhost:5000:

@task(1)
def hello_world(self):
    self.client.get("http://localhost:5000")

Для последующих задач необходимо изменить номер, как показано ниже:

@task(1)
def hello_world(self):
    self.client.get("http://localhost:5000")
@task(2)
def index(self):
    self.client.get("http://localhost:5000/index")

Если нужно выполнить POST-запрос, используйте следующий код:

self.client.post("/login", {"имя пользователя": "admin", "пароль": "admin"}).

По завершении можно добавить внутрь класса дополнительную фичу, такую как wait_time:

  • wait_time — обозначает время ожидания между выполнением задачи. В данный момент будем использовать between(0.5, 3.0), которая указывает на время ожидания между 0,5 и 3 секундами. Доступны и другие встроенные функции, такие как constant и constant_pacing. Позже мы изменим это значение на 0 для нагрузочного тестирования.

wait_time = between(0.5, 3.0)

Финальный код будет выглядеть примерно так:

from locust import HttpUser, task, between

class WebsiteTestUser(HttpUser):
    wait_time = between(0.5, 3.0)

    def on_start(self):
        """ on_start is called when a Locust start before any task is scheduled """
        pass

    def on_stop(self):
        """ on_stop is called when the TaskSet is stopping """
        pass

    @task(1)
    def hello_world(self):
        self.client.get("http://localhost:5000")

Функции on_start и on_stop специально оставлены пустыми. Одно из основных вариантов их использования — это добавление в них вызовов login и logout для проверки аутентификации сайта.

Тест

Давайте протестируем его, открыв другую командную строку и указав в ней каталог, в котором находится locustfile.py. Если вы используете точно такое же имя, то просто выполните команду:

locust

Если же используется другое имя, пропишите такую команду (соответственно изменив имя файла):

locust -f personal_directory/your_file.py

Вы получите следующий результат:

Откройте браузер и введите следующий URL:

http://localhost:8089/

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

Нажмите кнопку Start swarming (Начать роение), когда все будет готово. Процесс запустится, и вы увидите изменения:

  • Request — Общее количество запросов, сделанных на данный момент

  • Fails — Количество запросов, которые не были выполнены

  • Median — Скорость ответа для 50-го процентиля в мс

  • 90%ile — Скорость ответа для 90% перцентиля/мс

  • Average — Средняя скорость ответа в мс

  • Min — Минимальная скорость ответа в мс

  • Max — Максимальная скорость ответа в мс

  • Average bytes — Средний размер ответа в байтах

  • Current RPS — Текущее количество запросов в секунду

  • Current Failure/s — Общее количество отказов в секунду

Перейдите на вкладку "Графики", и вы увидите следующие графики:

Изображение автора
Изображение автора
Изображение автора
Изображение автора
 Изображение автора
Изображение автора

Остальное меню предназначено для работы с ошибками и исключениями. На вкладке Download Data можно даже скачать данные в формате csv. Вы можете заметить, что RPS в данный момент довольно низкий. В основном это связано с тем, что мы установили время ожидания (wait_time) в диапазоне от 0,5 до 3 секунд. Для реального нагрузочного тестирования измените оба значения на 0. Также можно использовать функции constant(0) в зависимости от ваших предпочтений. Перезапустите тест, и вы увидите максимальное значение RPS, которое может выдержать ваш сервер. Попробуйте поэкспериментировать, используя различное количество пользователей (number of users) и скорость загрузки (hatch rate). 

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

3. Интерфейс командной строки (CLI)

Модуль также дает возможность запускать нагрузочное тестирование через CLI, что позволяет легко реализовать автоматизированный процесс. Просто добавьте no-web параметры при запуске locust. Также необходимо указать хост, количество пользователей и скорость загрузки.

locust -f locustfile.py --no-web --host wfng -c 1000 -r 100

f — путь к файлу

no-web — Запуск моделирования без веб-интерфейса

c — Количество пользователей

r — Скорость загрузки (Hatch rate)

Запустите программу на 30 секунд и остановите ее с помощью команды Ctrl-C. Вы увидите следующие выходные данные:

Есть и другие полезные параметры, например:

t — Остановка через определенное время. 30 с, 5 м, 1 ч, 1 ч 30 м.

csv — Сохранить результат в файлы в формате CSV.

Ознакомиться со всеми доступными параметрами можно с помощью команды:

locust --help

4. Заключение

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

Затем мы создали тестовый сервер на Flask. Одновременно с этим мы исследовали функциональность, предоставляемую модулем, написав простой скрипт Locust. Мы запустили тест и получили результаты в пользовательском веб-интерфейсе. Также получили графики и данные, доступные для скачивания в формате CSV.

Кроме того, мы попробовали запустить то же самое моделирование через CLI — что помогает создать автоматизированный флоу нагрузочного тестирования.

Спасибо за прочтение и надеюсь, что вам понравилось это руководство. До новых встреч в следующей части!

Ссылки: 

  1. https://docs.locust.io/en/stable/installation.html

  2. https://locust.io/

В заключение приглашаем всех, кому интересна тема автоматизации тестирования на Python, на бесплатный открытый урок, который пройдет сегодня вечером. На встрече поговорим, какие перспективы у профессии в данный момент и какие требования предъявляют кандидатам на собеседованиях. Обсудим современные технологии автоматизации тестирования и преимущества использования автотестов в 2023 году. Урок проведет Андрей Гридяев — Lead QA Automation Engineer в Semrush. Записаться можно по ссылке.

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