У camunda слишком много имен, в которых можно запутаться.
На текущий момент существует 2 версии камунды 7 и 8(камунда - это в целом набор разных продуктов, а не единое целое).

Между ними почти нет ничего общего, поэтому их следует различать.

В этой статье будут описаны проблемы специфичные в целом для 7 версии, но иногда будут комментарии как проблема решена в 8 версии.

Какие задачи решает Camunda

Camunda - это инструмент оркестрации для бизнес-процессов в bpmn нотации.

Основные возможности camunda это:

  1. Поддержка долго-живущих процессов и их хранение

  2. Планирование и выполнение процессов

  3. Версионирование bpmn-схем. За счет этого система остается в состоянии пригодным для внесения изменений в долгосрочной перспективе

  4. Устойчивость к ошибкам за счет повторного выполнения заданиий(at least once)

  5. Визуализация бизнес-процесса(bpmn-схема при этом является исполняемой и благодоря этому всегда в актуальном состоянии)

  6. История выполнения процессов - упрощение поддержки

Работа с контекстом

Как хранить

Camunda поддерживает несколько форматов для хранения контекста:

  1. JVM сериализация

  2. JSON

  3. XML

Основная проблема с форматом данных - это поддержка обратной совместимости. С JVM сериализацией это делать очень проблематично, поэтому проще брать JSON/XML.

Что в 8-ке

Контекст сохраняется только в JSON формате

Что хранить

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

Хорошей практикой является использование внешнего хранилища для ваших данных, а в контексте хранить только id.

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

Что в 8-ке

В 8-ке один инстанс процесса может занимать до 4 МБ в целом.

Область видимости переменных

В камунде область видимости переменных делится на глобальные и локальные.
Глобальные чаще всего инициируются из кода(при старте процессов, при корреляции и в делегах).
Это осложняет понимание процесса, так как не видно какими данными оперирует процесс.

Делегаты камунды можно представлять просто как функцию с входящими/исходящими переменными и тогда чтение bpmn-схемы станет проще. Но для этого нужно, чтобы переменные были отражены в самой bpmn схеме.
Это возможно только при использовании локальной области видимости в делегах и маппинга переменных на схеме.

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

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

Что в 8-ке

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

Проблемы с корреляцией

Camunda из коробки предлагает API для работы с корреляцией:

  1. Ожидание событий на bpmn-схеме

  2. Корреляция сообщений из bpmn-engine

Типичный сценарий ожидания событий
Типичный сценарий ожидания событий

Race condition

На этой схеме происходит обычная гонка. Между блоками "Добавить задание в очередь" и "Задание выполнено" есть задержка по времени, которая приводит к тому, что в момент уведомления о выполнении задания процесс еще не готов принимать сообщение(возникает ошибка MismatchingMessageCorrelationException).
По этой ошибке нельзя точно понять ждал ли кто-то событие вообще или оно давно не нужно.

Эта проблема даже описана в книге "Practical Process Automation" от авторов Camunda(Глава 9/BPMN and Being Ready to Receive).
В качестве решения этой проблемы в книге предлагается делать следующее:

  1. Перед корреляцией добавить небольшую задержку в несколько сотен миллисекунд(как временное решение)

  2. Использовать буфер для сообщений(готовой реализации в 7-ке нет)

То есть в 7-ке из коробки эта проблема не решается.

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

Решение номер один - это подписку на событие сделать глобальной. В этом случае она будет активна всегда.

В таком сценарии возможна ошибка OptimisticLockingException, которую можно просто ретраить

Подписка на событие активна всегда
Подписка на событие активна всегда

Решение номер два - это отдельная таблица для подписок на события.

Внешнее хранилище подписок
Внешнее хранилище подписок

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

Параметры корреляции

Есть несколько признаков, по которым можно сопоставить событие и процесс ожидающий его:

  1. ID инcтанса процесса

  2. Бизнес-ключ процесса

  3. Сопоставление переменных процесса

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

Единственным вариантом здесь является использование собственного механизма подписок описанного выше.

Что в 8-ке

Для решения проблемы готовности процесса принимать события был добавлен встроенный буфер сообщений.

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

Выполнение джоб

В камунде два основных способа выполнения пользовательского кода: делегаты и externalTopic.

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

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

Обработчик может находится в том же приложении, что и bpmn-движок(из коробки оно так не работает и нужно написать это с нуля).

В плане выполнения джоб camunda - это очередь поверх БД.
У каждой джобы есть заданное кол-во попыток на выполнение. Блокировка джоб происходит на уровне данных, а не через механизмы в БД(в таблице джоб есть время до которого задание блокируется).
Время блокировки нужно настраивать, чтобы не было ошибочного и параллельного выполнения одной и той же джобы.

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

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

Для БД PostgreSQL есть локальная оптимизация в виде активации флага ensureJobDueDateNotNull, которая немного оптимизирует запрос на поиск джоб для выполнения

Что делать с историей

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

Для сохранения истории есть паттерн по ее вынесению во внешнее хранилище описанный в статье Как сохранять историю процессов в Camunda без вреда для них.

Это решение не идеальное, но рабочее и дешевое.
Лучшим вариантом будет хранение истории в clickhouse или других хранилищах подходящих под эти цели(это решение более трудоемко).

Нужно так же не забыть:

  1. Выбрать корректный уровень истории под ваши нужды

  2. Настроить ttl в процессах

  3. Включить очистку истории(при использовании внешнего хранилища, очистку можно включить 24/7)

Масштабирование

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

Одна из оптимизаций, которую там реализовали - это построение кластера из нескольких брокеров.
Тоже самое можно провернуть и с 7-кой, так как неважно на каком брокере будет запущен экземпляр процесса и будет выполняться(у каждого брокера должна быть своя БД).
В случае с 7-кой механизм репликации между брокерами не нужен, так как есть стандартные паттерны репликации БД.

Кластер Camunda 7 + внешнее хранилище истории + excamad = Победа

Кластер Zeebe
Кластер Zeebe

Что не так с Camunda 8

  1. Самая главная проблема - это изменение лицензионной политики. Начиная с версии 8.6 камунда становится платной

  2. Из-за того что все воркеры внешние, то увеличивается задержка времени работы процессы, так как на каждую джобу происходит минимум 2 сетевых запроса(получение джоб воркером и завершение джобы)

  3. Из-за резкого изменения лицензии open source инструменты не успели появиться и навряд ли появятся

Материалы:


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

Аве, оркестрация!

Комментарии (8)


  1. ganqqwerty
    14.09.2024 16:02

    А расскажите, кто использует инструменты типа камунды? Просто ж если технари - то почему они делают это не в коде, а в диаграммке, а если не технари - то как они в блоках этой диаграммки исполняют какие-то скрипты?

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

    Или тут похожая история на LabView?


    1. bespaltovyj Автор
      14.09.2024 16:02
      +3

      Camunda - это не инструмент для документирования.
      В camunda схемы являются исполняемыми.

      >Просто ж если технари - то почему они делают это не в коде, а в диаграммке

      Так же camunda не является инструментом для визуального программирования.
      В BPMN-схеме определяется последовательность шагов и взаимосвязь между ними.

      BPMN движок берет на себя работу по сохранению состояния сценария, перехода между блоками и подобного и такие вещи глобально не имеет смысла писать с нуля.
      В camunde код все равно нужно писать и очень много(тот который находится внутри блоков)

      >если не технари - то как они в блоках этой диаграммки исполняют какие-то скрипты?

      Если схема должна быть исполняемой, то это невозможно.
      Код все равно придется писать


    1. sergey-gornostaev
      14.09.2024 16:02
      +3

       если технари - то почему они делают это не в коде

      И в коде тоже, Камунда - это не no-code, а оркестратор. К Камунде обычно приходят тогда, когда сложность бизнес-процесса дорастает до того уровня, что будучи полностью выраженная в коде порождает просто неподъёмный уровень цикломатической сложности программы. Плюс, бизнес-процессы могут быстро и сильно изменяться, дорабатывать код в таком же темпе и осуществляться огромные миграции старых процессов на новые просто перестаёшь успевать, с Камундой это проще.


  1. olku
    14.09.2024 16:02

    Есть ли ей простые альтернативы?


    1. eastywest
      14.09.2024 16:02

      Spring State Machine


    1. bespaltovyj Автор
      14.09.2024 16:02

      На вряд ли.

      Можно рассмотреть Temporal в качестве альтернативы.
      Но на самом деле оно не так сложно как кажется на первый взгляд.


    1. ggo
      14.09.2024 16:02

      Я бы сказал, наоборот.

      В относительно простых процессах, без большой нагрузки, без требований по доступности, без требований по TTM, (критерии можно дальше продолжать) - Camunda вполне ок.

      Если любой из критерием выше не выполняется - я сегодня Camunda'у из списка вычеркну.

      Это не значит, что Camunda не может нагрузку держать. Если ее долго и мучительно тюнить - вполне может. Правда в этот момент приходит осознание, что без Camunda'ы во втором случае было бы легче, но выпиливать ее уже никто не даст, кучу усилий закопали в ее тюнинг.


      1. olku
        14.09.2024 16:02

        У меня сложилось впечатление, что 10 лет назад она воспринималась бизнесом как low code, которым не является. Запрос на low code есть всегда, меняется лишь количество альтернатив, которые его предлагают. Лямбды и кубер расширили возможности.