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

Для их реализации мы исследовали и опробовали некоторое количество инструментов, среди которых были Apache JMeter и написанный нами на Python скрипт LogSniper, который выполнял реплей заранее подготовленных серверных логов с HTTP-запросами на цель.

От использования JMeter было решено отказаться из-за значительной сложности подготовки и проведения тестов, высоких требований к производительности нагрузочного стенда и довольно малых мощностей нагрузки, хотя эти недостатки и компенсировались высокой информативностью собираемой статистики. LogSniper был отклонен из-за малой мощности генерируемой нагрузки и здесь даже простота подготовки нагрузочных HTTP-пакетов не смогла перевесить. Другие известные инструменты нам по тем или иным причинам тоже не подошли.

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

Что это

Яндекс.Танк — инструмент для проведения нагрузочного тестирования, разрабатываемый в компании Яндекс и распространяемый по лицензии LGPL. В основе инструмента лежит высокопроизводительный асинхронный генератор нагрузки phantom: он был переделан из одноименного веб-сервера, который «научили» работать в режиме клиента. При помощи phantom можно генерировать десятки и сотни тысяч HTTP-запросов в секунду (http-requests per second, http-rps).

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

Некоторые полезные ссылки:

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

Сравнение производительности двух аналогичных веб-сервисов

В ходе работы нам потребовалось сравнить характеристики двух веб-сервисов, работу которых можно примерно описать как «прозрачные HTTP-прокси, перенаправляющие входящие запросы на backend-приложение».

Общую схему работы можно изобразить следующим образом:

image

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

В качестве стенда web-proxy на схеме использовались два тестируемых веб-сервиса, с которых при помощи агента Танка снимались показатели производительности. Условно назовем их Эталонный веб-сервис и Испытуемый веб-сервис. Нам требовалось понять, соответствует ли производительность испытуемого веб-сервиса эталонному.

Для backend использовалось небольшое веб-приложение, запущенное под Nginx и возвращающее одну простую HTML-страничку.

Выявленные ограничения

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

Характеристики стенда backend-приложения:

  • 8 vCPU, 4 GB, 10 Gb/s,
  • веб-сервер Nginx.

Максимальная отдача сервера, которой удалось добиться, составила ~ 25 000 http-rps, но и при нагрузке выше 25k http-rps работа стенда не была нарушена.

Стенд Танка с характеристиками 16 vCPU, 8 GB, 10 Gb/s позволил реализовать нагрузку до 300 000 http-rps.

Пропускная способность виртуальной среды ESXi, определенная с помощью Iperf, составила 8 Gb/s в одну сторону, 4 Gb/s при двухсторонней нагрузке между двумя виртуальными машинами.

Метрики и критерии сравнения

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

  • http_rps_out — значение http-rps, отправляемое с Танка на веб-приложение,
  • http_rps_in — значение http-rps, принимаемое на Танке со стороны веб-приложения,
  • http_request_size — размер http-запроса в байтах,
  • send_requests — количество отправленных HTTP-запросов,
  • bs_out — bytes per seconds, байт в секунду — параметр определяет скорость отправки данных с Танка,
  • bs_in — значение bs, отправляемое с веб-приложения в сторону Танка,
  • test_time — время теста в секундах,
  • response_time_med — среднее время, в которое укладывается 90% всех ответов.

Зная число HTTP-запросов и их размер, получаем, что bs и http-rps связаны по формуле: bs = http_rps * http_request_size.

В данном случае мы решили выбрать следующие критерии для сравнения работы веб-сервисов под нагрузкой:

  1. За все время теста значение параметра «время, в которое укладывается 90% ответов» у испытуемого веб-сервиса должно быть не больше, чем у эталонного веб-сервиса.
  2. На отрезке возрастания нагрузки на очередные 1000 http-rps значение параметра «время, в которое укладывается 90% ответов» у испытуемого веб-сервиса должно быть не больше, чем у эталонного веб-сервиса.
  3. За все время теста общее количество правильно обработанных запросов у испытуемого веб-сервиса должно быть не меньше, чем у эталонного веб-сервиса.

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

Тестовые HTTP-запросы

Для одного из профилей нагрузочных тестов нам требовалось создать смешанный HTTP-трафик из GET- и POST-запросов с линейным возрастанием нагрузки до 10k http-rps в течение 10 минут.

HTTP-запросы, вошедшие в патрон Яндекс.Танка

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

Сбор данных и анализ результатов

После подготовки запросов мы просто запустили Танк стандартным образом и выполнили нагрузочный тест со смешанным трафиком для обоих тестируемых веб-сервисов.

Результаты для эталонного веб-сервиса

Информация веб-монитора Танка:

image

Информация консоли Танка:

image

Результаты для испытуемого веб-сервиса

Информация веб-монитора Танка:

image

Информация консоли Танка:

image

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

  1. Испытуемый сервис удовлетворяет первому критерию, так как для 90% запросов среднее время ответов для испытуемого сервиса не превышало такой же показатель для эталонного сервиса.
  2. Требование второго критерия выполнялось для каждого этапа нагрузки.
  3. Судя по анализу статус-кодов ответов, записанных в журналы Танка, испытуемый веб-сервис принял и корректно обработал запросов больше, чем эталонный веб-сервис.

 

Выводы

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

Кроме того, он хорошо внедряется в имеющиеся системы автоматизации. Например, для упрощения работы со стендом Танка — управления, запуска, подготовки патронов для лент, контроля за процессом тестирования и сбором результатов — мы без особых усилий написали класс-обвязку на Python, который подключается к стенду по SSH и выполняет все перечисленные действия. Затем этот класс был встроен в нашу существующую систему авто-тестирования.

Дополнительно вы можете посмотреть, как подключить и использовать высокопроизводительную систему Graphit для анализа большого числа графиков (о ней рассказывалось в одной из презентаций на конференции YAC-2013). Ее также можно приспособить для нужд нагрузочного тестирования с использованием Яндекс.Танка.

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

By Ruslan Novikov

Интернет-предприниматель. Фулстек разработчик. Маркетолог. Наставник.