От монолита к микросервисам: как мы применяем Temporal.io для оркестрации кода
Всем привет!С вами IT-команда Поле.РФ, и сегодня мы расскажем, как механизм Temporal помогает нам автоматизировать многочисленные бизнес-процессы. Объясним, почему мы остановились на этом решении, а также поговорим о его сильных и слабых сторонах.
Как мы описывали бизнес-процессы раньше?
Первоначально, мы использовали кастомную стейт-машину. Переходы и права доступа хранились в объемных JSON-файлах, которые обрабатывались кодом на Kotlin с применением подходов функционального программирования. Такая монолитная архитектура не позволяла гибко работать над бизнес-процессами по отдельности.
И это оказалось большой проблемой! Со временем число команд увеличилось, бизнес-процессы усложнились, а работая с монолитом, каждое, даже самое незначительное изменение, требовало много времени на реализацию. Онбординг по работе с машиной состояний и ее траблшутинг также стали слишком трудоемкими.
Из каких альтернатив мы выбирали?
Помимо того, что можно переписать декларативную стейт-машину, существуют еще два варианта, как реализовать бизнес-процессы в коде:
● Использовать BPM-движок, например, Camunda. Несмотря на его популярность, мы отказались от этого решения. Оно достаточно тяжеловесное, а переход на новый метод потребовал бы длительного погружения разработчиков DevOps-специалистов. Не говоря уже об аналитиках – не так просто описывать все процессы в BPMN-нотации!
● Внедрить Workflow-механизмы для оркестрации кода. Мы изучили опыт международной компании-гиганта: не так давно Uber разработала Cadence и гибко автоматизировала переходы между состояниями внутри бизнес-процессов.
Как выстроена реализация бизнес-процессов сейчас?
Для себя мы выбрали второй путь, используя сервис Temporal.io. Ребята из нашей команды уже умели работать с этим инструментом, поэтому мы смогли быстро внедрить его. А теперь пару слов о том, как все устроено на практике.
Базовым строительным кирпичиком для Temporal является Activity – метод Kotlin-класса. Из набора Activity строится Workflow – тоже простой метод в Kotlin-коде, который описывает, в какой последовательности нужно обращаться к Activity. Оснащенное механизмами Retry Policy, новое решение имеет высокую отказоустойчивость и позволяет адаптироваться к ограничениям нагрузки и пропускной способности.
Нашу работу с сервисом мы начали с использования паттернов Publisher/Subscriber и Transactional Outbox для переноса фоновых и асинхронных процессов на Temporal. Следующим шагом, мы применили паттерн CQRS для синхронных бизнес-процессов, описывая их в нотации Event Storming.
Какие существуют ограничения при работе Temporal?
Однако помнить, что Temporal не предназначен для хранения данных. Входные и выходные значения записываются, но если бизнес-процессы очень разветвлены и задействовано много переменных, можно легко превысить лимиты, поэтому стоит перекладывать полученные данные во внешнее хранилище, либо реализовывать Sticky Activity.
Какие вы преимущества Temporal вы назовете?
Мы выделили для себя несколько плюсов в работе с новым решением, и среди них:
● Можно работать с микросервисами, причем не только в Backend-части, но и во Frontend-приложениях.
● Удобные интеграции с внешними системами. Retry Policy, которую мы уже упоминали, помогает нам распределить нагрузку по обработке и контролировать частоту обращений к внешним системам.
● Более простой траблшутинг благодаря Custom Search Attributes – так мы можем быстро и точечно найти обработку процесса конкретного клиента, продукта или заявки.
● Получение дополнительных кастомных метрик и тщательный мониторинг. Теперь мы легко можем найти медленные этапы в бизнес-процессе, или отловить аномалии и выбросы на накопленных данных.
На этом все 😌 Однако мы знаем, что это далеко не последний вызов для нас, и будет еще множество других. Самое важное – это сокращение time to market для бизнес-фичей, сохраняя при этом качество продукта и непрерывность работы платформы.