Проверка портала региональных госуслуг под нагрузкой через puppeteer

Сегодня мы решили поделиться опытом нашей команды по тестированию и участию в подготовке регионального портала услуг к предоставлению услуги «Запись в первый класс».

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

В процессе подготовки к пиковому проведению записи в первый класс работали несколько команд, т.к. в неё вовлечены, так или иначе: оператор ЦОД, эксплуатант и разработчик информационной системы регионального портала, эксплуатант и разработчик интегрированной информационной системы образования, техническая поддержка пользователей регионального портала. Мы в iondv выполняем последнюю задачу, независимо отслеживая работоспособность портала и поддерживая пользователей.

Наша роль в подготовке – организация тестирования и рекомендаций по конфигурациям кеширования в nginx, ну и мы готовили инструкцию для пользователей с рекомендованным «поведением».

Услуга на востребованный ресурс как техническая задача

Проблема в услугах, подобных «записи в 1-й класс» в интегральном показателе нагрузки (или вероятности запросов) стремящемся к «дельта функции» (δ-функция, функция Дирака) – хорошо видна на графиках в виде пики. В этот момент происходит кратный рост обращений в краткий период времени.

Наш опыт говорит, что основная задача подготовки вовсе не в том, чтобы увеличить ресурсы. Задача — максимально уменьшить потенциальное кол-во запросов в секунду, растянуть их на какой-то период и подготовить систему к оставшейся нагрузке. При этом надо найти и ускорить узкие места — это даст самый большой эффект в соответствии с принципами теории ограниченных систем (принципы Голдратта). И иначе именно самое узкое место откажет. Вся система должна работать от него: принцип «барабан-буфер-веревка».

Физически невозможно в 10-ти минутных песочных часах просыпать весь объем за 1 минуту – очевидно, что они разрушатся. Аналогично и для предоставления услуги. Никого не удивляет — когда перед МФЦ очередь и скандалы на получение услуги, но всех удивляет — почему портал лег.

Есть разные модели поведения обработки нагрузки из теории массового обслуживания :

  • можно ставить пользователей в ожидание, т.е. наращивать очередь;
  • можно просто отказывать в обслуживании тем, кто пришёл позже, например, пока не будут обработаны предыдущие;
  • можно пытаться бесконечно наращивать производительность.

Целесообразность где-то посередине. Ведь для услуги с ограниченным ресурсом, предоставляемой регионом или государством, важна не только скорость, но и, в первую очередь, сохранение социальной справедливости – т.е. равные условия у всех. В тоже время – если пользователь не получил то, что ему нужно, он инициирует новый запрос. В этом случае запросы растут лавиной, формируя модель атаки «эффект собачьей стаи» (dog-pile effect, cache stampede, hit miss storm) – пользователь запрос уже отменил и инициировал новый, а предыдущий ещё в очереди стоит на обработку.

Этот процесс усиливает то, что в подаче участвуют целыми семьями — папа и мама заполняют заявления одновременно, и часто подают заявления несколько раз для надежности. А кроме того, часто ещё и в нескольких вкладках и нескольких браузерах. Поэтому ожидаемую пиковую нагрузку обычно имеет смысл умножать в 2-3 раза, от количества тех, кто фактически подает заявления в подобных услугах.

Организация оказания услуги

Мы сделали расчет ожидаемого количества заявителей на основе комбинации данных об общем количестве поданных заявлений в прошлому году и поминутным данным по другим регионам. Обычно пик заявлений приходится на 5-10 минуты, в том числе потому что первые три-пять минут порталы почти не отвечают, а позже пользователи заполняют форму от 1 до 5 минут (не удивляйтесь многие даже в таких «нервных» условиях заполняют с телефона).

Примерная модель расчета для условных 1000 заявлений в час такая:

  • пик с 5 по 10 минуту с момента начала и будет подано 80% заявлений по правилу Паретто
  • условно планируем 160 заявлений в минуту или 3 заявления в секунду.

По факту первая подача произошла через одну минуту и 45 секунд, а пик заявлений шёл с 4 минуты.Для уменьшения нагрузки на ЕСИА и на систему от генерирования сессий авторизации в инструкции предложили пользователям авторизоваться заранее и удлинили время жизни сессии. По факту 50% были авторизованы за 1 час, а ~90% за полчаса. Мы сталкивались ранее с тем, что пользователи начинали заходить на портал за 10 минут до начала услуги — и авторизация начинала работать нестабильно. Сложно сказать почему. Возможно причина в том, что когда в Москве проводятся технические работы ночью — у нас в Хабаровске как раза начало рабочего дня.

Убрать «дельта функцию» при перезагрузке формы в 00:00 часов невозможно. Весь смысл этой процедуры в том, что услуга появляется в заданное время. Но можно постараться уменьшить кол-во запросов браузера на всех ожидаемых маршрутах пользователей и тем самым оставить нагрузку на систему только от необходимых — форма, динамические справочники и отправка заявления.

Сами настройки nginx достаточно стандартны. Здесь важнее подобрать ограничения, которые может выдержать система. Их и подобрать — т.е. начинать ставить в очередь запросы, когда сервер ожидаемо подойдет к границе своих возможностей.

Ну и самое важное — мы принудительно проставили кеширование (proxy_cache) и увеличили время жизни данных «expires» в nginx для всех путей статики и где возможно динамических страниц, в которых нет сессий. Это кстати частая ошибка при кешировании — записывать в кеш данные (иногда даже статику), в которых сохранена чужая сессия, выход обычно удалять эти куки из заголовков, если сервер не может разделять типы данных.

В браузере для пользователя это выглядит как обновление страниц из файлов загруженных с диска или памяти. Но даже когда у пользователя они получаются с сервера — они берутся из кеша nginx. Сами справочники конечно же в самой системе закешированы.

Это уменьшило кол-во потенциальных запросов с 89-запросов до 14 и объем с 2,1 Мб (для 1000 обновивших страницу пользователей это потенциальный пик 4-8Гбит/с) до 38Кб (мы все помним про webpack, но для entrprise платформ это не всегда легко сделать). По результатам прохождения – надо ещё было кешировать не только в системе, но и в nginx часть справочников с формы и динамических классификаторов не используемых в пиковый момент и проставлять для них принудительно время жизни. А при росте нагрузки вообще имеет смысл выставлять на главную полностью статичную страницу с маршрутизацией пользователей на нужную услугу или делать отдельный ресурс для услуги.

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

Оптимизацию самой системы описывать не буду — при нагрузочном тестировании выявлялись узкие места — в основном в запросах к СУБД и оптимизировались индексы и сами запросы.

Наверное самой главной оптимизацией является упрощение формы. Что сильнее всего влияет на скорость при реализации в форме?

  • загрузка файлов — при загруженном канале, это существенно увеличивает нагрузку на него и систему, особенно при загрузке сканов большого размера. Математика тут простая — типичная фотография на смартфоне сейчас занимает 5-10Мбайт (привет владельцам новых iPhone у которых низкое разрешение на камерах просто не поддерживается) и для 5-ти документов дает использование одним пользователем до 375 Мбит/с канала (1 байт считаем примерно равным в трафике 10 битам, хотя при кодирование файлов application/x-www-form-urlencoded – это 20 бит), а 100 пользователей в минуту это дает 625 Мбит/с. В регионах где ширина арендованных каналов к ЦОДам редко превышает 100Мбит/с это может стать неожиданным сюрпризом — так как начнется отказ в обслуживании по таймаутам. Пользователи будут нервничать, перегружать и это приведет к «эффекту собачьей стаи». Обычно первый вопрос — зачем нам нужны эти файлы? Если оригиналы все равно приносят, то часто их можно опустить. А если это копии, то какая юридическая значимость в них?
  • сложные справочники. Нагрузку повышает обычно использование адресного справочника ФИАС или КЛАДР. Проблемы здесь в силу размера — ФИАС занимает до 40Гбайт в БД и поиск по нему занимает время. Десятые доли секунды, но умноженные на 1000 одновременных запросов — нагружают любую систему. Без специальной подготовки, возможно в виде отдельного веб-сервиса и на отдельном ресурсе, сложно выдержать нагрузку — поэтому часто для адреса используют обычное текстовое поле.

Ну и перейдем собственно к тестам.

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

Тестирование делали через puppeteer – путем эмуляции действий пользователя в браузере Crominium. Янедекс.танк и JMeter отбиваются защитой от атак, т. к. генерируют множество однотипных запросов. Кроме того эти тесты слабо совпадают с профилем реальных запросов при изменении поведения системы под нагрузкой. Кроме того сервера кешируют запросы, а часть процессов в них воспроизвести сложно (например авторизацию). Кстати, с одного из семинаров devDV у нас есть выступление с презентацией по вопросу использования puppeteer для тестирования, в т.ч. нагрузочного, ссылка на видео .

Для начала мы составили профиль поведения пользователя и процедуру разбили на ключевые этапы:

  1. массовая авторизация в ЕСИА
  2. единовременное обновление формы услуги,
  3. массовая подача

На каждый из этапов мы делали отдельный тест. В прошлом году на этапе авторизации в ЕСИА были сложности, но протестировать его полномасштабно затруднительно. Система внешняя, срабатывает защита от атак и баны на авторизации. Тем не менее можно сформировать профиль тестов для проверки именно узких мест тестируемой системы — обычно это количество одновременно авторизованных сессий и плановые значения авторизаций в минуту, которые можно регулировать рекомендациями.

В тесте важна обертка для организации нескольких потоков, мы используем 'puppeteer-cluster'. Но обычно более сложным является обработка исключений и изменения поведения портала под нагрузкой — часто выявляются элементы верстки, которые всплывают по два раза. Или элементы не проявляются, если какие-то данные загрузились не так, как ожидалось. Это все те ошибки, которые увидят и пользователи и перезагрузят страницу — а значит создадут дополнительную нагрузку. Здесь два пути — реализовывать в тесте обработку исключений. Или дорабатывать портал.

Сам тест простой. Ниже фрагмент от клика на кнопку «Вход» на портале услуг до ввода данных в ЕСИА.

Проверка обновления формы заявления в ожидании пользователями «открытия записи». Тест на перезагрузку по сути одношаговый, но важно проверять типы возвращаемых ошибок – сетевая это проблема, ошибка nginx, ошибка сервера и соответствует ли форма критериям. А сложность в том, чтобы сгенерировать максимальный объем запросов за наименьшее кол-во времени и не попасть под ограничения защиты (впрочем на время тестов её можно изменить, с другой стороны, это тоже проверка настроек сетевой и серверной инфраструктуры и WAF).

Такие тесты на puppeteer требует достаточно много ресурсов для работы. Де факто получилось, что нужно не менее 2-х ядер против 1-го ядра фронтенд подсистемы и очень широкий канал. Но при аренде их в облаке — это вполне доступно. Мы пользовались Яндекс.облаком.

В тесте сначала реализуется авторизация в ЕСИА для каждого потока отдельно. После этого запускается на каждый поток отдельный браузер и в рамках одной инстанции проводится заданное кол-во обновлений. После этого инстанция перезапускается. Сама проверка может включать типовой путь, например главная страница, форма услуги. Но чаще достаточно только полного обновления услуги и проверки необходимого справочника, что услугу можно подать — все как в инструкции для пользователей.

Фрагмент теста по открытию главной и обновлению страницы.

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

Фрагмент.

Кстати, прохождение теста можно ускорить, если вводить все данные не из из puppeteer конструкцией await page.type, а перенести эту логику в сам браузер. Но тогда возрастает сложность отлавливания ошибок.

Например так

Во время тестов мы обеспечивали несколько тысяч авторизаций ЕСИА и около 16 тыс. отправленных заявлений. Как проводилось восстановление продуктивной информационной системы образования после такого кол-ва заявлений — даже не спрашивайте. Это совсем другая история.

Главный видимый результат этого процесса оказался в том, что местным СМИ в дни записи в первый класс теперь было скучно. Услуга ушла из медийной области.

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

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

0
Комментарии
-3 комментариев
Раскрывать всегда