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

11 Окт 2018   |   Разработка

Практически каждая веб-студия в своей деятельности так или иначе сталкивается с задачами по оптимизации производительности. Как правило, это происходит тогда, когда сам клиент обращается к разработчикам с запросом вроде: “Сайт жутко тормозит, сделайте что-нибудь!”. В подавляющем большинстве случаев это означает как минимум одну из проблем:

  • Неоптимизированный или плохо оптимизированный код;
  • Ограничения хостинга (низкий тариф, слабое “железо”, сетевые задержки).

И когда уже поздно, тогда и начинаются поиски “узкого горлышка” в производительности сайта. Когда никто не обладает информацией о том, какую нагрузку в состоянии выдержать сайт, можно легко выкинуть деньги на ветер, заказав рекламную кампанию (в том числе контекстную) на каком-нибудь крупном портале и получив в результате посещаемость, которую система выдержать не может. Лучше, что в этом случае можно сделать - остановить рекламу, но не всегда это возможно (когда, например, вы заранее проплатили всю сумму за размещение баннера на другом сайте, и снимать его уже никто не будет).

Поэтому, говоря о производительности сайта, уместно вспомнить поговорку: “Готовь сани летом, а телегу зимой”. Это значит, что нужно заранее получить представление о том, сколько же посетителей сайт может выдержать. Какие же вопросы нужно задать себе ещё тогда, когда сайт работает быстро? Нам видится следующий список:

  1. Каково максимальное количество посетителей на сайте, при котором скорость генерации страниц является ещё комфортной для пользователей?
  2. Каково максимальное количество посетителей на сайте, приводящее к его полной недееспособности (отказ от сервиса)?
  3. За счёт чего сайт выйдет из строя при повышении нагрузки (в первую очередь): процессорного времени, исчерпания оперативной памяти, закупорки сетевого канала?

Последний пункт особенно важен, когда ожидается наплыв новых пользователей (например, за счёт рекламной кампании), так как в их браузерах ещё нет закэшированных ресурсов с вашего сайта (стилей, картинок, js-скриптов). Если ширина сетевого канала не очень большая, то сайт может выйти из строя попросту из-за трафика. Для того, чтобы ответить на эти и другие вопросы, проводится нагрузочное тестирование, для которого существуют специальные сервисы.

Какие есть сервисы и на что обратить внимание при тестировании

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

При выборе сервиса нагрузочного тестирования:

  1. Что именно позволяет измерить сервис: только время генерации страниц или же полное время загрузки? В последнее входит и нагрузка на nginx, который обычно и ответствен за выдачу статического контента (javascript/css/картинки);
  2. Вообще как много данных (таблиц, графиков) сервис предоставляет для анализа (чем больше данных и чем удобнее они представлены - тем лучше);
  3. Сервис позволяет тестировать только определённую страницу или же поддерживает возможность создания достаточно сложных сценариев вроде оформления заказа?
  4. Есть ли возможность проводить тесты по расписанию, откладывать выполнение на определённое время? Это особенно важно, если мы захотим протестировать ночью, ведь мало кто захочет специально для этого нарушать свой сон.
  5. Каковы лимиты на одновременное количество соединений, хватит ли вам нагрузочной мощности?
  6. Как долго идёт пинг от нагрузочного сервера до вашего (чем меньше, тем лучше).

При проведении тестов:

  1. Если вы хотите найти узкие места на сайте, то проводить тесты имеет смысл с выключенным кэшем (как самого Битрикса, так и низкоуровневого вроде кэша MySQL). Для его отключения нужно предусмотреть специальные скрипты, которые можно установить на cron.
  2. Проводя тест сразу на максимальных настройках (количестве параллельных соединений), вы рискуете “уронить” сервер. Проводите последовательность тестов, постепенно увеличивая потоки.
  3. Также обязательно отключайте контроль активности в Битрикс (или добавляйте исключения), иначе нагрузочные сервера быстро будут забанены, а оплаченный тест выполнится вхолостую.
  4. Убедитесь в том, что максимальное количество соединений в MySQL выставлено в большее значение, чем прогнозируемое количество потоков тестирования (в противном случае вы получите ошибку базы данных “Too many connections”).

На какие цены ориентироваться?

В первую очередь, нужно понять, что именно вы хотите проверить.

Если вам достаточно узнать, сколько одновременных соединений выдержит сервер при запросе определённой страницы (например, главной, карточки или списка товаров), вероятно, вам подойдут бесплатные варианты. Например, loadme позволяет на протяжении 50 секунд создавать нагрузку до 200 потоков, это очень много!

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

На текущий момент возможность тестировать до 100 одновременных соединений стоит около $100 в месяц. Но есть и исключения, например, blazemeter, где за те же деньги можно получить в 10 раз больше (минус в том, что тестировать вы сможете лишь время генерации страницы, а не полной загрузки со всем содержимым, что менее показательно).

Когда мы искали наиболее подходящий сервис под наши цели, мы остановились на loadimpact.com. Он позволяет делать замеры полной загрузки страницы со всей дополнительной нагрузкой на nginx, что по факту оказывается достаточно важным.

Отдельно хочется подчеркнуть важность определения сценариев нагрузочного тестирования. Тут не всё так просто, и ключевая ошибка может закрасться с самого начала. Несмотря на то, что общая цель нагрузочного тестирования всегда так или иначе связана с желанием понять запас прочности сайта в плане его производительности, не всегда понятно, на что тратятся основные серверные ресурсы. Чтобы что-то тестировать, нужно иметь план тестирования: куда отправлять нагрузочных ботов. Иначе вы можете направить нагрузку на те части сайта, которые вообще не являются узким местом  –  и получить очень хорошие результаты. А когда вместо ботов придут реальные пользователи  –  получите отказ от сервиса.

Это значит, что этапу запуска тестов всегда должен предшествовать этап моделирования действий пользователя. Открытие карточки товара или даже списка товаров вообще не эквивалентно оформлению заказа (в плане нагрузки). А оформление 16 заказов по 50 позиций и одного на 800 позиций  –  это тоже совершенно разное.

Рекомендация №1. Перед тем, как составлять сценарии нагрузочных тестов, пристрастно изучите всю уже имеющуюся статистику. В идеале разместите на сайте как можно больше целей Яндекс.Метрики или Google.Analytics. Посмотрите картину по тем пользователям, что уже посещают ваш сайт: как они себя ведут, на какие страницы заходят, какие действия совершают и куда кликают.

Например, может выясниться, что поиск по сайту играет очень важную роль. Или же им вообще не пользуются (тогда не особо критично даже то, что он тормозит). Посмотрите, каково среднее количество товаров в заказах пользователей. И максимальное количество.

Суть в том, что высока вероятность, что при повышении количества посетителей сайта пропорционально возрастёт количество именно тех действий, что они уже совершают. И соотношение между ними будет примерно тем же. А это будет значить, что нужно направлять ботов именно на востребованные действия, не забывая ни об одном из них.

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

  1. Заход на главную страницу сайта;
  2. Заход в список товаров;
  3. Заход на последнюю страницу в списке товаров (постраничная навигация);
  4. Заход в карточку товара;
  5. Сортировка списка товаров;
  6. Переключение количества товаров в списке (20/50/100 и т.д.);
  7. Фильтрация товаров (компонент умного фильтра);
  8. Поиск по сайту;
  9. Добавление товара в корзину (из карточки/списка товаров);
  10. Регистрация на сайте;
  11. Авторизация на сайте;
  12. Заход на страницу корзины с небольшим количеством товаров;
  13. Заход на страницу корзины с большим количеством товаров;
  14. Оформление небольшого заказа;
  15. Оформление большого (оптового) заказа;
  16. Оформление быстрого заказа (обычно через спец. форму).

Рекомендация №2. Воспользуйтесь профилировщиком Битрикс для сбора и анализа базовой статистики по затратам серверных ресурсов.

Несколько примеров

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

...то это почти наверняка значит, что сервер стал (быстро) выдавать ошибку, за счёт чего время реакции резко сократилось после скачка. В данном конкретном случае был достигнут лимит подключений к MySQL (Too many connections).

Далее приведём в пример некоторые случаи, с которыми мы сталкивались, и сделаем некоторые выводы. Вот график, предоставленный blazemeter’ом по нагрузке выбранной страницы тестируемого сайта:

На нём синяя линия - количество потоков, оранжевая - время ответа сервера (по сути, время генерации страницы). На протяжении первых минут кол-во потоков постепенно увеличивается до 50, а потом некоторое время держится на этом уровне до завершения теста.

А теперь запустим этот же тест на loadimpact.com (с теми же параметрами):

Здесь уже три линии: 1) Зелёная (верхняя) показывает количество потоков. Мы выставили те же настройки - постепенное увеличение до 50, что мы и видим; 2) Синяя линия означает время полной загрузки всех объектов на странице (html, css, js, картинки); 3) бордовая - время генерации html.

В данном случае мы видим полное подобие кривых общей загрузки и генерации html с примерной разницей в 1.5-2 секунды. Это достаточно хороший результат.

В целом же по данным графикам мы можем сказать, что сервер готов выдерживать нагрузку в 15-20 потоков без ощутимого падения производительности. При дальнейшем увеличении потоков будет пропорциональное замедление. В рамках теста на 50 потоках отказа сервера мы не получили, хоть он и выдавал страницу медленно (по 12-18 секунд).

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

Обратите внимание, что цена деления (масштаб) для бордовой и зелёной линий разная (подписи слева и справа от графика). Помимо того, что здесь в принципе страница генерируется очень медленно, ещё и разница между генерацией и загрузкой весьма ощутима. Вот некоторые значения с графика:

Потоков

Время генерации

Время полной загрузки

7

3,68 с

9,93 с

9

4,63 с

9,87 с

10

5,55 с

10,37 с

Такая разница может быть объяснена тем, что на данной странице расположено большое количество подключаемых объектов (js-скриптов, стилей, картинок) - 271 шт. Поэтому и важно измерять общее время, а не только генерацию, разница может быть в 2-3 раза. И для конечного пользователя важна именно полная загрузка.

Кейс: нагрузочное тестирование для интернет-магазина автозапчастей

Перед началом сезона к нам обратился клиент с просьбой оценить “запас прочности” своего интернет-магазина, чтобы понять, сможет ли он выдержать приток посетителей (помимо сезонного всплеска ожидалась и повышенная маркетинговая активность). Специфика отрасли такова, что подобные сайты оперируют большим количеством данных при выполнении поисковых запросов (десятки и сотни тысяч товаров, миллионы аналогов, постоянные выгрузки и синхронизации с 1С). Поэтому нагрузка сама по себе всегда велика, страницы открываются дольше, чем в обычных интернет-магазинах.

Нагрузочное тестирование задумывалось как пилотажное (и с соответствующим бюджетом), поэтому сценарии были крайне просты и не покрывали всего того количества важных ситуаций, о которых мы упоминали выше. Они должны были стать предметом будущих проверок.

Перед проведением теста на сайте был выключен всякого рода кэш (самого Битрикса, базы данных MySQL). Результаты сведены в следующую таблицу*:

A

B

C

D

E

G

Описание страницы

Созданная нагрузка (потоков)

Сред. время генерации (с)

Среднее время загрузки (с)**

Макс. нагрузка сети (Мбит/сек)

Комфортность хита для пользователя (%)

Главная

100

0,535

2,26 / 2,8

650

36

Карточка товара

100

1,15

1,15 / 2,3

302

43

Список товаров

100

3,6

1,2 / 4,8

192

21

Поиск по цифровому артикулу

100

0,32

1,5 / 1,82

397

55

Поиск по буквенно-цифровому артикулу

100

2,7

1 / 3,7

204

27

Полнотекстовый поиск

50

10,8

0,8 / 11,6

26

9

* Здесь имеет смысл сказать, что для полноты картины нужно собирать данные и составлять несколько таких таблиц  –  для разного количества потоков. То есть одни и те же страницы должны анализироваться, например, для 10 потоков, 20, 50, 100, 200 и т.д. Тогда будет видно то количество потоков, на котором начинаются проблемы с производительностью.

В нашем случае стояла конкретная задача посмотреть производительность сервера на 100 потоках, что и отражено в таблице (кроме последней строки, которую проверять на 100 потоках не имело смысла, так как уже на 50 были обнаружены серьёзные проблемы).

** В ячейках это колонки указаны парно: первое значение в паре являет временем с момента, когда страница отдана сервером, до момента, когда она полностью скачана клиентом; второе значение в паре  –  время с момента отправки запроса и до моммента его полного скачивания. По сути, второе значение является суммой времени генерации страницы и собственно её скачивания.

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

  1. Анализ абсолютных значений по столбцам

Он позволяет выделить среди всего количества страниц потенциально проблемные. Это не значит, что именно они будут создавать основную нагрузку, потому что это напрямую связано с востребованностью этих страниц. А по этим данным нельзя сказать, как часто пользователи запрашивают ту или иную страницу (но это можно узнать по Яндекс.Метрике).

Время генерации (колонка “C”)

Мы видим, что список товаров и поиск по буквенно-цифровому артикулу работают достаточно медленно, а полнотекстовый поиск  –  недопустимо медленно. При этом буквенно-цифровой поиск и список товаров  –  востребованные страницы. Это значит, что они вполне могут создавать основную нагрузку на процессор (из тех страниц, что попали в тестирование). Напротив, главная страница и поиск по цифровому артикулу генерируются сервером достаточно быстро. Карточка товаров  –  на границе приемлемого значения.

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

Время загрузки (колонка “D”)

В этой колонке значения поделены на два: первое значение  –  это непосредственное время скачивания данных, а второе  –  время полной загрузки для клиента (генерация + скачивание). Для клиента наибольший интерес представляет время полной загрузки, потому что это, фактически, его время ожидания. И тут мы можем получить общую картину того, сколько придётся ждать клиентам сайта. Если мы видим значения более 1.5 секунд  –  это повод подумать над тем, как улучшить ситуацию.

Нагрузка на сеть (колонка “E”)

Абсолютные значения в ячейках этой колонки показывают, какую ширину канала нам нужно выбрать, чтобы выдержать нагрузку. Но тут есть ряд оговорок. Тест проводится для случая новых пользователей. Фактически, это означает, что кэш их браузера пуст. Если в каждую единицу времени к нам будут приходить новые посетители  –  то результат будет именно такой, как в таблице. Если же нам придёт 100 пользователей, которые начнут ходить по сайту, нагрузка на сеть будет существенно меньше (потому что общие для всего сайта статические ресурсы будут закэшированы).

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

Комфортность хита (колонка “F”)

В этой колонке за 100% принята скорость загрузки страницы за 1 сек. Значение в 50% будет значить, что страница открывается в 2 раза дольше по сравнению с эталоном. В идеале все значения должны быть от 100% и больше. В нашем же случае всё наоборот  –  все значения существенно не дотягивают до этой границы.

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

  1. Анализ абсолютных значений по строкам (между столбцами)

Например, следует обратить внимание на случаи, когда время генерации страницы мало, а время загрузки  –  велико. В нашем случае это отчётливо заметно на данных по главной странице сайта (первая строка таблицы), которая отдаётся сервером за полсекунды, а загружается  клиенту –  за три. Также мы видим, что именно эта страница создаёт максимальную нагрузку на сеть  –  при данных условиях это 650 Мбит/сек. Очевидно, что здесь что-то не так, и можно подозревать чрезмерно большое количество статики (изображений, стилей, шрифтов, javascript-кода) на странице. В нашем случае так и есть. Имеет смысл провести её оптимизацию: во-первых, убрать со страницы то, что можно убрать; во-вторых  –  сжать то, что можно сжать (оптимизировать изображения по их размеру и качеству, объединить и сжать javascript и css).

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

  1. Общий анализ столбцов между собой

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

В плане сети мы можем увидеть, например, что 100 Мбит-ного канала для такого сайта вообще недостаточно. Здесь определённо нужен как минимум 1 Гбит (а лучше два).

Также мы видим (колонка “D”), что время, уходящее на скачивание данных, достаточно велико. И в некоторых случаях оно пятикратно превышает время генерации (поиск по цифровому артикулу). Вообще говоря это повод не только оптимизировать всю статику на сайте, но и передать задачу по её доставке специализированным сервисам  –  CDN. Это позволит разгрузить сеть, по которой явно наблюдается перегруз (колонка “E”).

Колонка “G” демонстрирует возможные показатели общей удовлетворённости работой сайта со стороны конечных клиентов (с точки зрения его производительности). И в нашем случае они оставляют желать лучшего.

Какие выводы мы можем сделать?

  1. Страницы списка товаров и поиска по буквенно-цифровому артикулу нуждаются в оптимизации производительности;
  2. Логика полнотекстового поиска нуждается в серьёзной оптимизации производительности и, вероятно, в полном пересмотре алгоритмов;
  3. На сайте требуется провести сжатие статики. Особо тщательно должна быть проанализирована в этом плане главная страница;
  4. Рекомендуется использовать CDN;
  5. Пропускную способность сетевого канала лучше повысить до 1 Гбит/сек на постоянной основе.
  6. На протестированном уровне нагрузки сервер, очевидно, начал тормозить на ряде страниц. Если сетевой канал будет 100 Мбит, то сервер с нагрузкой не справится. При 1 Гбит-ном канале хоть и наблюдаются задержки, но ошибок отказа от сервиса мы не получили, сервер продолжил работать.

Итоги

Нагрузочное тестирование – очень важная и трудоёмкая задача, требующая учёта множества факторов для своей реализации. Перед проведением основного тестирования следует собрать все необходимые данные и, желательно, совершить несколько пилотажных запусков на ограниченных мощностях.

Результаты нагрузочных тестов особенно значимы при ожидаемом всплеске посетителей, что всегда нужно учитывать перед маркетинговыми кампаниями или сезонными изменениями (вроде всплесков спроса на цветы накануне 8 Марта или автошины в межсезонье). Но задачи тестирования как такового гораздо шире: это и поиск узких мест производительности на сайте, и определение “запаса прочности” сервера, и проверка балансировки нагрузки в веб-кластере, и подготовка нового сайта к публикации на продакшн.

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

Вернуться к списку
Отправить сообщение