Яндекс.Танк и автоматизация нагрузочного тестирования

    В ходе тестирования некоторых продуктов компании 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-запросы, вошедшие в патрон Яндекс.Танка
    GET /loadtest/index.php?id=1&login=user&pwd=password HTTP/1.1
    X-Sniffer-Forwarded-For: yandex-tank-example-domain.ptsecurity.ru
    Host: backend-example-domain.ptsecurity.ru
    User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
    
    POST /loadtest/index.php HTTP/1.1
    X-Sniffer-Forwarded-For: yandex-tank-example-domain.ptsecurity.ru
    Host: backend-example-domain.ptsecurity.ru
    User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
    Content-Length: 32
    
    id=1&login=user&pwd=password
    
    
    POST /loadtest/index.php HTTP/1.1
    X-Sniffer-Forwarded-For: yandex-tank-example-domain.ptsecurity.ru
    Content-Type: multipart/form-data; boundary=validFile
    Host: backend-example-domain.ptsecurity.ru
    User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
    Content-Length: 150
    
    --validFile
    Content-Disposition: form-data; name="login"; filename="validFile.txt"
    Content-Type: text/plain
    
    Valid file content
    --validFile--
    
    

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

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


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

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

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

    image

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

    image

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

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

    image

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

    image

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

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

    Выводы


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

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

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

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

    Автор: Тимур Гильмуллин (блог).
    • +57
    • 32,3k
    • 4
    Positive Technologies 190,01
    Компания
    Поделиться публикацией

    Вакансии компании Positive Technologies

    Комментарии 4
    • +5
      Парни, спасибо вам за отличную статью. А вот как можно к этому прикрутить Jenkins — clubs.ya.ru/yandex-tank/replies.xml?item_no=246
    • 0
      Отлична система! Правда те нагрузки на которых она нужна требуют тщательной подготовки стендов и каналов связи. На реальном интерфейсе упирался в производительность чипа сетевой карты, который полноценный гигабит не обеспечивал при отдаче кешированных данных от nginx))
      Для простых смертных лучше подойдут online-сервисы, чьи ip гарантированно будут в белых списках провайдера. А на локальной машине решил использовать ламповый ab из apache-utils.
      • 0
        ab тоже можно использовать как генератор нагрузки в Танке. О том, как настроить, написано в документации.

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

      Самое читаемое