Веб-разработка

Битрикс остается, нагрузка уходит: архитектура отдельного сервиса на Flask

7 
 

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

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

В рассматриваемом проекте каталог вырос до более чем 4 000 продуктов. При отображении нужно было учитывать регион пользователя, отрасль, категорию и дополнительные параметры. Система также должна была синхронизироваться с внешними справочниками и поддерживать работу региональных администраторов.

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

Почему не стали продолжать оптимизацию существующей модели

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

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

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

Мы сравнили 2 сценария: глубокую доработку действующей платформы и вынос каталога в отдельный сервис. Второй вариант оказался понятнее по срокам и будущей поддержке.

Почему выбрали Flask

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

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

Поэтому серверную часть построили на Flask. Он позволил подключить только нужные компоненты и сохранить полный контроль над структурой приложения.

В качестве базы использовали MySQL. На сервере уже работала система веб-аналитики Matomo на той же базе, что упрощало развертывание и сопровождение.

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

Миграцию отделили от рабочей системы

Исходный интерфейс Битрикс не был рассчитан на быструю массовую выгрузку. Чтобы получить около 4 000 продуктов, скрипту приходилось последовательно обращаться к нему примерно 4 000 раз.

Выгрузку запускали ночью. Данные собирались в файл размером около 100 МБ, после чего обрабатывались уже независимо от Битрикс.

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

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

Массовые выгрузки перестали нагружать базу

Обычные пользовательские запросы обрабатывались с постраничной выдачей. Система возвращала ограниченное количество продуктов, а не весь каталог.

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

Раз в час отдельная задача готовила статический файл размером около 150 МБ. Когда поступал запрос на полный каталог, сервер отдавал этот файл без построения тяжелой выборки.

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

Такая схема снизила нагрузку на базу при массовых выгрузках в 10 раз.

Изображения очистили от дубликатов

В исходном каталоге одни и те же изображения могли храниться несколько раз. При прямом переносе каталог медиафайлов занял бы около 500 МБ.

Перед загрузкой каждого файла система рассчитывала хеш SHA-256. Если файл с таким же хешем уже существовал, повторная копия не сохранялась. В базе создавалась ссылка на ранее загруженный объект.

После удаления дубликатов фактический объем изображений составил около 20 МБ.

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

Основная сложность находилась в старых данных


Разместите
тендер бесплатно

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

Заполнить заявку 13590 тендеров
проведено за восемь лет работы нашего сайта.


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

Идентификаторы регионов назначались произвольно и не совпадали с федеральными кодами. Например, внутренний номер Москвы нужно было заменить на код 77.

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

Особенно сложными были категории с разной глубиной классификации. Если в одной системе отрасль была разделена на 60 направлений, а во второй только на 30, однозначного технического решения не существовало. Нужно было принимать бизнес-решение: какие категории объединить и какие связи сохранить.

Миграция старых данных в подобных проектах редко сводится к переносу строк. Она требует согласования смыслов.

Записи размером до 1 МБ потребовали отдельного решения

Некоторые продукты содержали большую историю и множество документов. Размер их данных доходил до 1 МБ.

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

Создание отдельной документной базы ради небольшой доли тяжелых записей было бы избыточным. Мы заменили тип поля в MySQL на MEDIUMTEXT, который поддерживает объем до 16 МБ.

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

Историю изменений упростили

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

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

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

Даже для часто изменяемых продуктов такая выборка занимала менее 50 мс.

Исходные идентификаторы продуктов сохранили. Это позволило поддержать существующие ссылки через перенаправления и не потерять накопленную видимость страниц.

Существующие корпоративные сервисы не дублировали

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

Уведомления передавались в существующую очередь RabbitMQ. Новый сервис отвечал только за формирование сообщения. Отправка писем, СМС и внутренних уведомлений оставалась на стороне корпоративной платформы.

Защиту от распространенных веб-атак обеспечивал внешний шлюз заказчика. Мониторинг также был подключен к действующей системе.

За счет этого команда сосредоточилась на каталоге и его бизнес-логике. Создавать собственные подсистемы авторизации, рассылок, защиты и наблюдения не потребовалось.

Результаты

Во время испытаний сервис стабильно обрабатывал более 100 запросов в секунду на сервере с 4 процессорными ядрами и 8 ГБ оперативной памяти.

Нагрузочный сценарий включал просмотр продуктов, полнотекстовый поиск и фильтрацию по связанным данным. В стресс-тесте 100 потоков непрерывно открывали случайные страницы в течение нескольких часов. Система сохранила стабильность и приемлемое время ответа.

Полнотекстовый поиск через Sphinx занимал около 20 мс. Получение истории продукта выполнялось менее чем за 50 мс.

Код серверной части, миграторов и интеграций занял около 1 МБ. После упаковки дистрибутив занимал 5 МБ. Полный распакованный проект вместе с дизайном, скриптами и шрифтами занимал около 10 МБ.

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

Что можно вынести из этого проекта

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

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

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


Здесь я обычно пишу про проекты, кейсы и ИТ-практику. А если хочется увидеть меня не только в рабочих текстах - приходите в мой тг https://t.me/alekseypostrigaylo. Там - сын, поездки, работа за кадром, личные наблюдения и попытка жить так, чтобы было что вспомнить. 

Выскажите мнение
Авторизуйтесь, чтобы добавить свой комментарий.




9

Лучшие статьи

Поделиться: 0 0 0
Старший партнер в  Энсайн , Москва
 0  0  0

Оцените статью
Спасибо за оценку