Материал будет полезен людям, которые начинают свой путь в этом направлении, и поможет понять, на что нужно обращать внимание в первую очередь и как облегчить процесс проведения проверок.
Новости от клиента
«3000. Нет, лучше 5000 пользователей! — Как-то услышали мы от клиента вместе с новостью, что он планирует привлекать в приложение активных пользователей.
Что приходит? первое что приходит в голову, когда вы слышите об увеличении количества пользователей в приложении от 170 до 5000? Какие фичи заинтересуют этих пользователей или с каких платформ будет больше загрузок? Безусловно, это важные моменты. Но первые мысли, чтобы сервер не упал.
Планирование
Для начала мы выяснили у клиента основные цели маркетинговой кампании, а также на какие функциональные части приложения он хотел бы привлечь больше всего пользователей.
В идеальном мире для нагрузочное тестирования необходимо провести проверки всего в приложении, начиная от регистрации и заканчивая логаутом. Но с ограниченным дедлайном на помощь приходит оптимизация и поиск компромиссов.
План был таким:
- Выбрать фичи для нагрузочного тестирования и приоритезировать их.
- Определиться с инструментами для проведения нагрузочного тестирования.
- Составить план и провести расчеты.
- Создать отдельное окружение для тестирования.
- Провести ручное тестирование, чтобы проверить, все ли хорошо с frontend частью программы во время работы с большим количеством пользователей. И пофиксить баги.
- Составить тест-план и проверить нагрузку на небольшом количестве пользователей (10-20). Пофиксировать возникшие баги.
- Провести проверки для большего количества пользователей, постепенно увеличивая нагрузку на сервер и пофиксировать возникшие баги.
- Понять, какое максимальное количество активных пользователей может «выдержать» приложение.
- Предоставить отчет клиенту.
Инструментом для нагрузочного тестирования был выбран Apache JMeter. Его функции позволяют провести проверки в сжатые сроки и тестовые сценарии достаточно легко поддерживаются в актуальном состоянии, что пригодится, если понадобится тестировать повторно.
Настройка перед началом
Во первых. Cо стороны QA составили план проверок и расчетов, а команда бэкенда совместно с девопсом развернули новое окружение. По умолчанию тестовое окружение не рассчитано на работу с большим объемом отправляемых на сервер данных.
Поэтому наши специалисты выполнили настройки на новой среде с возможностью подключения дополнительных мощностей (серверов) при увеличении нагрузки.
Во вторых. Тест-план готов и согласован, окружение развернуто. И мы начали проводить ручные проверки.
В ходе тестов быстро нашлось несколько функциональных багов, связанных с логикой самого приложения.
Также нашли «потери» в виде не совсем актуальных и лишних запросов, которые остались из более старых версий и значительно тормозили работу приложения.
Первые проверки при низкой нагрузке
Пока первые баги исправлялись на стороне приложения, в JMeter развернулся тест-план согласованных фич. Приступили к первым проверкам для небольшого количества пользователей.
Тест-план состоял из 6 групп.
- Login.
- Follow/Unfollow сущности 1.
- Create/Delete сущности 2.
- Join/Left сущности 3.
- CRUD с данными сущности 4.
- Discussion (работа с чатами – самое коварное и самое интересное для тестирования).
К моменту проведения проверок в приложении на проде уже было 170 активных пользователей, поэтому первые проверки по нагрузке сервера прошли успешно. Радовало и то, что все найденные баги во время предварительного ручного тестирования уже исправили.
Увеличение нагрузки, количество ошибок и поиск их решения
Мы начали увеличивать мощности и количество пользователей. Для начала проводили проверки по каждому треду отдельно. Тесты 10, 25, 50, 100, 200 пользователей – все работало довольно неплохо. Логин отрабатывал «как часы», но «проблемы» начались при погрузке других сущностей — часть проверок просто выдавали 500 ошибки на 300 пользователях.
На скриншоте настройки тестирования. Предположим, что в тред-группе последовательно выполняются 5 запросов при работе 300 пользователей с задержкой в 1 секунду. Будут ли запросы работать как следует?
Ответ – нет, сервер будет возвращать ошибки.
Если увеличивается количество пользователей, нужно обращать внимание на Ramp-up period и давать возможность серверу успевать все в пределах допустимого времени. То есть плохим и малореалистичным будет сценарий, где мы даем для одного пользователя одну секунду на выполнение, допустим, 5 запросов, содержащих в себе разный набор данных (по количеству отправляемых параметров) в пределах одной тред-группы.
Величина периода определена с помощью измерений времени на выполнение ручной проверки сценариев — среднее значение между временем на выполнение запросов с обязательными и всеми параметрами.
После увеличения ramp-up period ошибок стало меньше, но они все еще возникали.
Следует обращать внимание на набор запросов, прогоняемых в рамках одного треда, и скорость их обработки сервером. Иногда сущности не успевают образоваться, соответственно работать с ними дальше невозможно.
В нашем случае для 300 пользователей был приемлем и реалистичен Ramp-up period в 30 секунд, то есть для дальнейших проверок минимальное соотношение количества пользователей к Ramp-up period было 10 к 1.
Пора подключать несколько тредов к работе одновременно.
Нагрузка из 300 пользователей в каждом из тредов, одновременно запущенных для проверок, дала свой результат — посыпались 500 ошибки. Сервер не выдержал нагрузку с одновременной работой 1800 пользователей. Началась работа на стороне бэкенд-команды по оптимизации запросов.
В то же время, на стороне JMeter в тестовых сценариях также проводилась оптимизация работы с логином и данными, которые передаются в параметры запросов.
Если в тест-плане несколько самостоятельных тредов, работающих одновременно, нужно выносить логин из тредов. То есть следует выполнять логин один раз во время выполнения проверок и просто передавать токены в другие треды. Так проверки будут оптимизированы и более приближены к реальным пользователям-флоу.
Небольшая оптимизация тест-плана и фиксы на стороне бэкенда позволили увеличивать нагрузку и смотреть на работу сервера. На 4000 одновременно работающих пользователей стали частично ломаться проверки чата. И снова — 500 .
Если в проверках есть параметры, которые могут генерироваться или выбираться рандомно, пользуемся этой возможностью и подключаем рандом. Это могут быть: отправка текстовых сообщений, генерация названий сущностей, работа с отправкой медиа и т.д.
Пост состоит в основном из медиа и текста. Для таких случаев и можно использовать рандом:
- Предварительно подготовим медиа и текст, с которыми будем работать в будущем.
- Для медиа нужно выбрать несколько поддерживаемых фото и видео различных форматов и размеров. Они могут храниться локально на ПК или в облачном хранилище проекта (второй вариант лучше, учитывая работу с тестами для всех членов команды). Затем необходимо указать путь к хранению этих файлов в HTTP Request и указать имя параметра, указывая его условный id (media_id):
- Для текста отлично подойдет словарь или собственный текст, который можно положить в переменную (но помните о цензуре – не стоит забывать, что все, что попадает на сервер, а затем и в саму программу, может быть доступно другим членам вашей или клиентской команды) ).
- При выполнении запроса вместо дефолтных параметров для каждого пользователя с помощью прописанного скрипта в PreProcessor мы отправляем рандомно выбранное медиа или набор слов/ фраз из массива текста.
В случае с текстом — достаточно в скрипте использовать функцию, которая разбивает строку (наш текст) на подстроки и, применяя функцию рандома, будет выбирать любую из них и отправлять, как параметр в теле запроса.
В случае с медиа используем функцию рандома, которая будет генерировать число от нуля до общего количества медиа, которые мы используем в тестировании. После этого подставляем сгенерированное число как id во имя переменной медиа (media_randomId) и передаем его как параметр в теле запроса.
При работе с рандомом следует обратить внимание как на реализацию через язык скрипта, которым вы пишете, так и на стандартную функцию рандома в JMeter:
${__Random(p1, p2, p3)}, где P1 и р2 — нижний и верхний предел случайного числа соответственно, а р3 — имя переменного, где будет храниться случайно выбранное число.
Со стороны бэкенда проведены исследования, оптимизированы запросы для работы чатов, а также пересмотрены настройки сервера и тарифных планов.
Когда речь идет о масштабировании проекта, следует думать о том, что работы только с одним сервером может оказаться недостаточной, ведь он имеет ограниченную мощность. Поэтому, когда на проекте возникает вопрос об увеличении пользователей или нагрузке на серверную часть, стоит подумать о расширении возможностей сервера или подключении дополнительных — для распределения нагрузки.
При возрастании нагрузки на сервер увеличивается объем оперативной памяти, CPU и т.п. Таким образом, по мере увеличения нагрузки появляется потребность в подключении дополнительных мощностей и происходит переход на следующий тарифный план (M10, M20, т. д.), а также подключаются дополнительные серверы -горизонтальное и вертикальное маштабирование.
Подумал о сервере — не забудь подумать о своей рабочей станции. Чтобы не перегружать CPU на своем компьютере, следует запускать тесты не с JMeter GUI, а из консоли, не забывая сохранять результаты тестов в файл для проведения анализа.
В течение 3 дней мы непрерывно нагружали сервер, запуская все треды одновременно. В каждом из них было от 500 до 1500 пользователей. Ошибки могли возникать только тогда, когда дополнительные серверы подключались для помощи. В итоге тестирования и оптимизации мы вышли на стабильность в работе с 3000-9000 пользователей.
Результат проделанной работы
Мы предоставили отчеты о проделанной работе клиенту и сошлись на том, что нагрузка в 9000 активных пользователей при запланированном росте до 20 000 зарегистрированных – очень хороший результат, которого мы смогли достичь в сжатые сроки. Для итоговых отчетов мы использовали генерируемые в течение последнего дня тестирования.
Для более наглядного результата можно было бы дополнительно подсоединить Grafana, которая предоставила бы интерактивную визуализацию для аналитики.
Если хочется нагляднее предоставить отчеты клиенту, следует совмещать графические отчеты, которые можно генерировать в самом JMeter, визуализацию отчетов в Grafana и табличные отчеты от JMeter.
Взяты с официального сайта Grafana.com
В результате мы справились с поставленной задачей и показали достаточно хорошие результаты работы программы. Релиз прошел, после завершения первой маркетинговой кампании количество активных пользователей выросло до 8000. Программа работала как часы, а клиент и наша команда были удовлетворены работой.