Скупили билеты за минуту: как микросервисная архитектура помогает туристическому сервису

Скупили билеты за минуту: как микросервисная архитектура помогает туристическому сервису

Зачем нужна микросервисная архитектура

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

С ростом сложности платформ и развитием функционала нормой стало микросервисное взаимодействие: когда зоны ответственности разбиваются на разные технические или доменные составляющие. Микросервисная архитектура – сложная технология, однако позволяет выносить отдельные задачи в разные сервисы. Кроме того, это про разделение зоны ответственности между командами и направлениями. Как правило, за каждый из микросервисов отвечает отдельная группа разработки, которая хорошо его знает и умеет быстро дорабатывать. Так становится легче внедрять изменения, а продукт получается более качественным.

Как биллинг стал микросервисом

Мы в RUSSPASS движемся по пути увеличения микросервисов. Биллинг как микросервис, недавно внедренный в RUSSPASS, отвечает за работу с заказами — создание, сохранение, редактирование, отчеты. Это не просто покупка — биллинг отвечает за учет тарифов, сеансов, скидок, промокодов, ограничений на продажу в каждом из мероприятий или объектов. Каждый из этих пунктов содержит множество строчек кода. За пределами биллинга находятся другие сервисы — оплата, эквайринг, формирование чека или получение уведомлений.

Скупили билеты за минуту: как микросервисная архитектура помогает туристическому сервису

Микросервисы и День гида

Микросервисная архитектура нужна в первую очередь, чтобы пользователи могли быстро, качественно и за минимальное время получить услугу. В части биллинга это решение помогает справиться с пиковыми нагрузками на сервис. Допустим, стартовала реклама, и на определенную страницу заходят сразу тысячи пользователей, которые начинают тут же оформлять заказы. Нагрузка подскакивает многократно. Так, например, произошло, на День гида, когда на RUSSPASS было доступно множество экскурсий с бесплатной регистрацией. Но этот большой наплыв посетителей сервис выдержал достойно. В такие “горячие” периоды микросервис старается делать так, чтобы пользователь ничего не заметил, а его клиентский путь оставался четким и безболезненным. Развернуть монолитное приложение — слишком объемная задача, это приведет к торможению сервиса, а вот микросервисы стартуют за секунду и помогают сгладить такие скачки.

Как мы подошли к разделению монолита на микросервисы

Стек, который мы используем — Java 21 (язык программирования), Spring Boot 3+ — (cовременный фреймворк для быстрого создания приложений на Java), Gradle (система автоматизации сборки проектов), JUnit 5 (фреймворк для модульного тестирования Java-приложений), PostgreSQL 17 (объектно-реляционная СУБД), Redis (in-memory база данных, используемая для кэширования), Kafka (передача сообщений в асинхронном режиме).

Ключ к успешному разделению — использование паттернов и итеративный подход.

Процесс разделения состоит из нескольких шагов

Шаг 1. Декомпозиция: мы провели анализ и разделяли биллинг по бизнес и техническим доменам.

Шаг 2. Разработчики проводят глубокий рефакторинг: исходный код разделяется по пакетам или модулям. Одна из сложностей при разделении — это целостность базы данных, то, как хранятся объекты в таблицах. Мы используем PostgreSQL, который позволяет иметь на одну базу несколько схем (schema). Доменные области, которые удается выделить, помещаем в отдельную схему. Эта процедура позволит отследить зависимости кода, от базы данных. Мы не должны допускать, обращения из сторонней доменной области к текущему домену. Используем инструмент «Checkstyle — ImportControl».

Шаг 3. После успешного выделения, мы выносим код в отдельный репозиторий, но база данных используется прежняя, паттерн «Shared database». Старый код удаляется из монолита

Шаг 4. В микросервисах данные разделены, мы используем паттерн «Database per service», необходимые данные запрашиваются по Rest API или забираем как события из Kafka (+ pattern transactional outbox). DBA переносит данные из одной базы, в целевую базу сервиса. Тут мы сталкиваемся с типичными проблемами — консистентности данных, компенсирующими транзакциями и задержками сети. Это требует более высокого уровня аналитиков, разработчиков. Мы регулярно проводим комьюнити встречи, на которых делимся опытом внутри компании и повышаем уровень компетенций.

3
Начать дискуссию