Привет, Хабр! С вами команда разработки платформы Russ Online Группы компаний Russ (входит в объединенную компанию Wildberries & Russ). Мы хотим поделиться историей о том, как от монолитной системы мы перешли к микросервисной архитектуре и облачным решениям на базе Kubernetes и S3. Эта трансформация создала фундамент для дальнейшего развития платформы и внедрения новых сервисов.
Платформа Russ Online: первые шаги
Пять лет назад мы запустили платформу Russ Online, чтобы автоматизировать процесс размещения рекламы вне дома по всей России. Основная цель платформы — предоставить рекламодателям и агентствам возможность самостоятельно управлять рекламными кампаниями: выбирать рекламные поверхности, настраивать стратегию размещения и следить за эффективностью кампании. Система позволяет не только подбирать локации для рекламы, но и получать подробные отчеты, включая эфирные справки, фотоотчеты и данные о перемещении рекламных материалов. На рисунке ниже представлен интерфейс платформы в настоящий момент.

На начальном этапе разработку разделили на два ключевых направления: создание пользовательского интерфейса и реализацию бизнес-логики с интеграцией внутренних сервисов. Платформа была создана на .NET Core 3.1 и состояла из двух монолитов, каждый из которых отвечал за свою часть системы. Этот подход позволил быстро запустить проект.
Развитие платформы и переход на новый стек
Спустя три года активного развития платформы перед нами встала задача масштабирования и оптимизации ее архитектуры. Мы провели комплексное преобразование, уделив особое внимание архитектуре, сопровождению кода и согласованности работы компонентов. Важным шагом стала модернизация контрактов взаимодействия: теперь сервисы возвращают HTTP-статусы с информацией об ответе, если статус неуспешный.
На начальном этапе развития платформы для обеспечения единообразия ответов от наших сервисов была разработана универсальная структура, представленная ниже:

В дальнейшем мы перешли на использование стандарта RFC-7807, согласно контракту Problem Details.
Когда вышла стабильная версия .NET 6, мы приняли решение обновить наш технологический стек. Это позволило повысить производительность и упростить поддержку системы, но в результате мы столкнулись с несовместимостью некоторых наших библиотек с новым фреймворком. Позже, с выходом .NET 8, мы начали разрабатывать новые микросервисы на этой версии, хотя еще остались сервисы на прежних версиях. Одновременно с обновлением стека технологий наша команда значительно выросла, что позволило нам взяться за более сложные и масштабные задачи. Несмотря на успешное развитие платформы на монолитной архитектуре, с ростом нагрузки и усложнением функциональности мы столкнулись с ограничениями в масштабировании и гибкости. Это стало ключевым фактором в принятии решения о переходе на микросервисную архитектуру.
От монолитов к микросервисам
Это трудоемкий процесс, так как каждый бизнес-домен требует разработки отдельного сервиса, а некоторые сервисы построены для выполнения только одной функции. Однако микросервисная архитектура позволила независимо разрабатывать, развертывать и масштабировать отдельные компоненты системы, что повысило ее гибкость и отказоустойчивость. Мы начали постепенно перемещать функционал из монолитов в микросервисы, не прерывая работу платформы.

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

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

Процесс миграции данных был многоуровневым: после разработки и тестирования нового механизма система поддерживала сразу оба подхода. Мы переносили тысячи файлов объемом от 50 Мб до 10 Гб. Они содержали различные данные, в том числе упомянутые выше фотоотчеты, которые наши клиенты заказывают для подтверждения размещения рекламных материалов. Благодаря тщательной подготовке мы провели миграцию незаметно для пользователей, после чего удалили различные артефакты старого подхода.
Итоги
Сразу после выпуска первой версии платформы мы сосредоточились на добавлении в монолитное приложение новых бизнес-функций. Этот период позволил нам быстро нарастить функциональность, а полученный опыт стал основой для масштабной работы над архитектурой.
Переход на микросервисную архитектуру и использование современных технологий, таких как Kubernetes и S3, позволили нам значительно повысить производительность, масштабируемость и надежность платформы.
Развитие нашей платформы убедило нас в том, что внимание к архитектурным решениям и качеству разработки является ключевым фактором для успешного масштабирования и поддержки сложной системы. Важно помнить: хотя разработка бизнес-функций является приоритетной задачей, нельзя пренебрегать техническими основами. Будем рады вашим комментариям!