[Программирование, Kotlin] Дорога к BPMN
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет! Меня зовут Лев, и я инженер в новосибирской команде интеграционных сервисов ДомКлик. Мы разрабатываем (микро)сервисы, которые связывают между собой множество разрозненных систем, а также делают многие процессы быстрыми и прозрачными для конечного пользователя. Мы используем ставший уже стандартным стек: Kotlin, Spring Boot, Hibernate, Liquibase и т. д. И нам для наших сервисов (на тот момент пока ещё одного) потребовался механизм исполнения бизнес-процесса. Требования к нему были следующие:
- каждое действие как отдельный независимый модуль;
- stateless-движок -> stateful-задача;
- перезапуск некорректно отработавших задач заранее заданное количество раз;
- возможность горизонтального масштабирования;
- механизм должен быть асинхронным;
- разработать его нужно максимально быстро и просто.
Custom Business Process EngineМы немного подсмотрели структуру сервиса у наших коллег, что-то добавили от себя, и получился у нас простейший движок следующего вида. Четыре базовых SpringService: JobProcessor, JobRunner, JobService и LaunchService, а также базовая сущность задачи — JobEntity. Разберём их подробнее. Самое первое и главное — сущность задачи (Job), вокруг которой построен весь механизм. Она имеет следующие поля:
- id — идентификатор задачи;
- status — статус исполнения задачи (PENDING, READY, INPROGRESS, COMPLETED, ERROR);
- runCount — текущее количество попыток исполнения текущей задачи;
- delayedTime — время, спустя которое можно повторить исполнение задачи (возрастает для каждой следующей попытки);
- archived — признак нахождения задачи в архиве;
- request — тут хранится сериализованный (JSON) запрос на исполнение задачи.
Поскольку наш сервис должен был быть асинхронным, да ещё и разрабатывался максимально срочно, мы использовали PostgreSQL в качестве персистентной очереди запросов. Запрос порождает в базе задачу.Исполнение вышеописанной задачи отдаётся следующим спринг-сервисам:
- JobProcessor имеет лишь один метод process(jobs: List<Long>), принимающий на вход список идентификаторов задач и запускающий их на исполнение методом run сервиса jobRunner.
- JobRunner тоже имеет лишь один метод run, вызываемый из JobProcessor. Он получает из jobService список задач по идентификаторам, проверяет, не превышено ли максимальное количество попыток вызова, и запускает задачу в launchService.
- LaunchService имеет один метод launch. Именно в нём и выполняются все бизнес-операции. При успешном исполнении статус задачи переводится в COMPLETED, иначе, в зависимости от значения runCount, возвращается в READY или завершается со статусом ERROR.
- JobService — основной сервис для работы с сущностью задачи. Он может класть в БД новую задачу, выбирать из БД задачу по идентификатору и по статусу, менять статус.
Custom Business Process Engine (+ Phases)Поскольку количество действий в бизнес-задачах начало расти, а при падении по каким-либо причинам сервис заново повторял весь процесс для задачи (особенно если на каком-то этапе было взаимодействие со stateful-сервисом), мы решили разделять бизнес-процесс на логические модули, назвав их фазами (Phases). Таким образом, сущность задачи получила новое поле phase и метод next(), возвращающий нам следующую фазу исполнения. Кроме того, JobService стал немного умнее и выбирает выполняемую над задачей операцию в зависимости от её текущей фазы. Теперь мы могли перезапускать процесс в случае ошибки не с самого начала, а лишь с фазы, на которой произошла ошибка. К тому же при горизонтальном масштабировании разные фазы задачи могут выполняться разными экземплярами сервиса, поэтому в случае падения одного или нескольких экземпляров сервиса задача будет подхвачена оставшимися.Теперь процесс исполнения запроса выглядел так. Контроллер сервиса вызывается по REST API и формирует в базе данных в таблице с задачами новую запись. Исполнением задач занимается SpringService JobRunner:
- Берёт задачу в статусе READY.
- Переводит её в статус IN_PROGRESS и записывает.
- Смотрит на фазу, и в зависимости от её значения выполняет какое-то действие. Для передачи данных и сохранения результата используется поле context, сериализованное в JSON.
- Если финальная фаза, то сервис переводит задачу в статус COMPLETE, сохраняет в базу и отправляет сообщение об успехе сервису-инициатору. Если фаза не финальная, то сервис переводит задачу в следующую фазу со статусом READY.
В случае ошибки:
- Если значение retries достигло maxRetries, то отвечаем сервису-инициатору ошибкой и возврашаем в базу задачу со статусом ERROR.
- Если значение retries меньше maxRetries, то делаем retries++ и возвращаем в базу со статусом READY.
Custom Business Process Engine (+ Phases) (+ Activiti)Наши сервисы разрастались, переходы между фазами переставали быть линейными, сценарии работы усложнялись, а код launchService и JobEntity.next() начал становиться нечитаемым и трудноподдерживаемым. С этим надо было что-то делать, и мы сделали! Ранее у нас был опыт работы с Activity, так что мы решили использовать этот BPMN-движок вместо последовательности фаз.
BPMN (Business Process Model and Notation) — нотация для описания бизнес-процессов, позволяющая представлять их визуально.
В интернете существует множество инструкций, как начать работать с Activity, так что здесь я это описывать не буду. Расскажу лишь про опыт использования. Главным достоинством стала возможность визуально представить процесс выполнения нашего бизнес-конвейера. Логика формирования данных в зависимости от условий теперь была более ясная, и это сократило количество ошибок при разработке. Например, нам требуется формировать разные пакеты документов для разных типов клиентов по сложному набору критериев. И когда таких критериев и типов клиентов становится слишком много, такие ветвления в коде уже перестают восприниматься визуально, а ошибки плодятся в разы быстрее. И тут нас выручает наглядная графическая схема процесса. Теперь LaunchService лишь выбирал и запускал нужный нам сценарий, а вся логика переходов была на картинке.Это было лишь переходным этапом, и приведя сервис к такой конструкции, мы начали понемногу выпиливать наш кастомный движок. Оставили все бизнес-процессы на Activity, чьи сценарии запускались уже из контроллера. В дальнейшем их обработку полностью отдали Activity.Однако это решение привнесло с собой и некоторые недостатки. Главными из них стали:
- Сложность отладки кода блоков. В Activity используется groovy-script, а сами схемы описываются огромными XML со встроенным groovy-script. Так мы получили трудноотлаживаемую часть проекта, разбросанную по *.bpmn xml-файлам.
- Наличие в проекте дополнительного языка (Groovy) усложнило поддержку проекта.
- Нет никакой валидации groovy-script в задаче Activity, а значит можно легко опечататься в названии метода или сигнатуре. При сборке не получится проверить валидность лишь модульными тестами.
- Проект не выглядит живым, на заведенную нами уже более года назад багу (https://github.com/Activiti/Activiti/issues/2911) ответ не получен до сих пор.
- Конкуренты (Camunda, Flowable) предоставляют более удобную и широкую функциональность и поддержку (а вот об этом в другой раз).
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, JavaScript, Программирование] Обновление вашего PWA в продакшене
- [Разработка под iOS, Разработка мобильных приложений, Разработка под Android, Тестирование мобильных приложений] 3 видео для мобильного разработчика
- [Программирование, Алгоритмы, Компиляторы, Софт] О реализации точного представления чисел или «где хранить деньги?»
- [Программирование, C, Программирование микроконтроллеров] К вопросу о сложении или как я нашел ошибку в gcc (на самом деле нет)
- [Программирование, Презентации] Как создать свой SlideShare
- [Программирование, .NET, C#] 6 малоизвестных фич C#/.NET (перевод)
- [Программирование, Машинное обучение, Учебный процесс в IT, Социальные сети и сообщества, Изучение языков] 9 Reasons Why Students Don’t Want You as a Teacher
- [Программирование, C++, Работа с 3D-графикой, Разработка игр, CGI (графика)] Vulkan. Руководство разработчика. Слои валидации (перевод)
- [Java, Scala, Kotlin, Kubernetes] IntelliJ IDEA 2020.3
- [Программирование, Разработка мобильных приложений, Разработка под Android, Развитие стартапа, Софт] Бизнес-идея для программистов. Совершенно незанятая ниша на рынке программ
Теги для поиска: #_programmirovanie (Программирование), #_kotlin, #_bpmn, #_bpmn_2.0, #_kotlin, #_blog_kompanii_domklik (
Блог компании ДомКлик
), #_programmirovanie (
Программирование
), #_kotlin
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:38
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет! Меня зовут Лев, и я инженер в новосибирской команде интеграционных сервисов ДомКлик. Мы разрабатываем (микро)сервисы, которые связывают между собой множество разрозненных систем, а также делают многие процессы быстрыми и прозрачными для конечного пользователя. Мы используем ставший уже стандартным стек: Kotlin, Spring Boot, Hibernate, Liquibase и т. д. И нам для наших сервисов (на тот момент пока ещё одного) потребовался механизм исполнения бизнес-процесса. Требования к нему были следующие:
BPMN (Business Process Model and Notation) — нотация для описания бизнес-процессов, позволяющая представлять их визуально.
=========== Источник: habr.com =========== Похожие новости:
Блог компании ДомКлик ), #_programmirovanie ( Программирование ), #_kotlin |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:38
Часовой пояс: UTC + 5