Эволюция HighLoad приложения на примере регионального портала госуслуг

image

«Завтра 20-е число, а значит снова будет шторм. Остановить его невозможно, только подготовиться и надеяться, что в этот раз пронесет, случится чудо, и наш озерный паром покорит океан». Такие мысли одолевали команду, занимающуюся поддержкой портала муниципальных услуг еще несколько лет назад. Как мы попали в эту ситуацию и как мы из нее нашли выход будет рассказано ниже.

Как всё начиналось


В далеких 1990-х годах область ЖКХ испытывала бум развития, внедрялись новые технологии, автоматизированные информационные системы, закупалась новая техника. Но кое-что оставалось долгое время практически без изменений, а именно платежки за квартиру. Да-да, те самые квиточки за квартиру, трансформировавшись в платежные документы, обретя штрих-коды, детальную расшифровку, оставались по-прежнему бумажками. Типовая схема работы расчетного центра предприятия ЖКХ или ресурсоснабжающего предприятия была следующей:

image

Постепенно модемный интернет заменялся на широкополосный доступ, возникла мысль — почему бы не получать онлайн платежные документы в электронном виде? В это же время сферу ЖКХ трясло и в организационном виде, МПП ЖКХ (муниципальное производственное предприятие жилищно-коммунального хозяйства) сменяли МУПы (муниципальные унитарные предприятия), ДЕЗы (дирекции единого заказчика). По итогам всех трансформаций произошло отчуждение ИТ-отделов предприятий ЖКХ, и на их базе родились всевозможные расчетные центры. Суть расчетных центров заключалась в, собственно, расчете квартплаты и информационном обеспечении населения.

Этап роста, 00-ые


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

image

Шли годы, порталы совершенствовались, появились возможности принимать показания приборов учета, формировать справки и т.д. Именно в это время на горизонте появились первые «тучки», все больше и больше пользователей начали регистрироваться на порталах и запрашивать данные. Вдали показалась первая волна приближающихся нагрузок.

Команда (далее — Команда 1) предприняла следующие меры по оптимизации:
— Изменение размера платежного документа в PDF с 0.5Мб до 0.2Мб
— Создание очереди формирования платежных документов
— Хранение сформированных платежных документов для повторного запроса
— Создание реплики основной базы, только для нужд портала

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

image

Этап большого скачка


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

Таким образом, следующим этапом стало отделение оперативной информации расчетных центров от информации, отображаемой в платежном документе. Для этого были разработаны простой формат передачи данных и база для хранения информации, проведен расчет необходимого для хранения места на 5 лет эксплуатации.

Ключевые решения, предпринятые на этом этапе:
— Отделение части информации оперативной базы данных;
— Разработка базы данных для хранения этого формата;
— Объединение данных расчетных центров регионов в единую базу данных;
— Интеграция с процессами портала, разработка сервисов.

На этом этапе решение из полноценного превратилось в бэкенд, так как портал предоставлял пользователям единый интерфейс. У портала была своя команда, которая разрабатывала его независимо от текущего решения расчетных центров. В нашей истории появляется вторая команда (далее — Команда 2) и новый вендор. Как увидим далее, это существенным образом повлияло на развитие и решение проблем. Суть проектного решения была следующей:

image

При проектировании БД принималось простое отображение формата в базу данных, в качестве СУБД был выбран PostgreSQL 9.3 (на тот момент вполне актуальная версия). Формат состоял из 9 плоских файлов, каждый из которых загружался командой COPY (читаем — очень быстро) в множество таблиц конкретного расчетного центра (у каждого расчетного центра был свой регистрационный номер) базы портала. В некоторых расчетных центрах количество записей, необходимых для формирования платежных документов, доходило до 1 000 000. В год это составляло до 12 000 000, за 5 лет -60 000 000. Количество запросов к данной базе увеличивалось до суммы всех пользователей районных порталов и могло составить десятки тысяч. Было, о чем задуматься.

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

Проблемы слишком быстрого роста


Портал был запущен, и подготовленные планы столкнулись с реальностью:
— Число пользователей превысило расчетное очень быстро
— Запросы шли к мастер таблице, но СУБД все равно опрашивало все таблицы
— Паразитная нагрузка на сервер БД. На этом сервере существовали другие, несравненно большие БД, информация в которые поступала в случайные моменты, загрузка ее забирала все доступные ресурсы
— Сервис формирования платежного документа тормозил вследствие неэффективной реализации
— Нагрузка от пользователей не равномерно раскладывалась по месяцу, а концентрировалась в двух периодах:
image
Этот момент и описан в начале поста. Сложно было диагностировать проблему, потому что проблемы казались во всех местах сразу. Команда 1 и Команда 2, одинаково любимые своим руководством, предпринимали шаги для выхода из ситуации, но общения между собой практически не было:
image
Команда 2 предприняла, казалось, логичный и полезный шаг: формирование платежного документа стало запрашиваться сразу после захода пользователя в систему, в расчете на то, что пока он по страницам доберется до нужного места, ПД уже сформируется, а готовый документ подтянуть можно быстро.

В это время Команда 1 каждый месяц героически решала по одной проблеме в месяц, каждый раз убеждая заказчика, что именно там скрывался корень проблемы:
— Оптимизировали SQL (получили рост производительности в разы);
— Отделили сервер базы данных для портала от остальных баз данных;
— Вынесли формирование платежного документа в отдельное приложение и тоже оптимизировали;
— Пересмотрели обращение к мастер таблице, поменяли версию PostgreSQL;
— Еще раз пересмотрели обращение (теперь от мастер таблицы запрашивалась только 1 конкретная партиция — еще ускорение в разы).

Героические усилия команд приводили к локальным успехам (2–3 месяца казалось, что проблема решена). Но реальность все время подбрасывала новые вводные:
— База данных уже содержала несколько лет и выросла более 1 Тб;
— Количество пользователей составляло уже сотни тысяч.

Пока шла борьба, Команда 2 настроила автоматический тест сервисов, так что о любой проблеме производительности становилось известно в считанные минуты и эскалация проблемы на самые верхние уровни управления происходила автоматически через электронную почту.

В это время в Команде 1:
— Время архивации БД стало превышать допустимы пределы (сервис становился недоступен);
— Одно обращение к сервису сразу затрагивало много месяцев, соответственно генерировало много запросов;
— СУБД стало хуже отрабатывать запросы из-за роста числа таблиц (партиций);
— Пользователи, которые хотели только внести показания приборов, все равно запрашивали формирование платежных документов (вспомним решение Команды 2).

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

В результате анализа (тут тема для отдельной статьи) предприняли следующие действия:
— Выполнили отсечение данных до 3-х последних лет, так как в предыдущий период обращений не было; тех пор ежегодно отсекается старый период;
— Переделали обращение к мастер таблице на обращение к конкретной партиции напрямую (снизили нагрузку на СУБД).

Настоящее время


Сейчас система достаточно стабильна, укладывается в регламентные сроки и требования по нефункциональным характеристикам, но на горизонте снова появились тучи:
— Дальнейший рост числа пользователей;
— Рост числа обслуживаемых домохозяйств;
— Увеличение сложности предоставляемых услуг;
— Рост детализации данных, доступных для пользователей.

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

image

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

Системный подход к решению проблем


Можем ли мы превратить опыт в методологию подхода к проблемам в Highload-проектах? Как ни странно, ответ ДА, все уже придумано за нас и находится в рамках Теории ограничений Э.Голдратта (Theory of Constraint TOC). Всего 5 простых шагов:

1. Найти ограничение (ограничения) системы.
2. Решить, как максимально использовать ограничение (ограничения) системы.
3. Подчинить все остальное этому решению.
4. Расширить ограничение (ограничения) системы.
5. ВНИМАНИЕ! Если за предыдущие 4 шага ограничение было устранено, вернуться к шагу 1, но не позволить инерции стать причиной возникновения ограничения системы.


Описание этой теории и суть шагов достаточно хорошо описаны в литературе в конце статьи, я же напишу свое видение в рамках текущего процесса:
1. Ограничение: время формирования платежного документа.
2. Решение: Формировать все платежные документы заранее, при загрузке данных.
3. Подчинить решению: При обращении пользователя выдавать готовый документ.
4. Расширить ограничение: Оптимизировать время формирования платежного документа.
5. Отказаться от системы предварительного формирования по ВСЕМ домохозяйствам, определить новое ограничение.

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

Что почитать по теме:


1. «Цель. Процесс непрерывного совершенствования», Элияху Голдратт
2. «Теория ограничений. Основные подходы, инструменты и решения», Дмитрий Егоров
3. «Теория ограничений Голдратта. Системный подход к непрерывному совершенствованию», Уильям Детмер

© Habrahabr.ru