Статьи

Создание распределенных приложений Workflow на Amazon с Camel

Трубопровод с SNS-SQS
Рабочий процесс состоит из независимых задач, выполняемых в определенной последовательности, определяемой динамическими условиями. Очень часто рабочий процесс представляет бизнес-процесс, например, этапы обработки заказа в интернет-магазине.

Amazon Web Services предлагают различные инструменты для создания распределенных и масштабируемых приложений рабочих процессов. Одним из подходов к созданию такого приложения является использование тем и очередей для соединения отдельных этапов в процессе рабочего процесса. Затем мы можем использовать публикацию / подписку, конкурирующих потребителей и другие механизмы для масштабирования нашего приложения, и вскоре даже самое простое приложение принимает форму, подобную этой:

AWS SNS-SQS - Процесс поддержки (2)
Каждый шаг конвейера связан со следующим с очередью, и каждый шаг выполняет некоторые действия и принимает решение, что является следующим шагом. Кроме того, использование SNS / SQS включает в себя некоторые другие задачи низкого уровня:

— Сериализация / десериализация данных

— Обеспечить согласованность (порядок FIFO) для SQSmessages

— Убедитесь, что размер сообщения не превышен

— Изобретите какую-то поддержку аудита

— Абонентские очереди по темам, назначение разрешений

— Управление DLQ

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

Простая служба документооборота
SWF, с другой стороны, предлагает API более высокого уровня для написания распределенных, асинхронных приложений рабочих процессов. Он автоматически сериализует / десериализует данные, управляет состоянием приложения, предлагает возможность аудита, гарантирует строгую согласованность, поддерживает несколько версий. Самое главное, это обеспечивает разделение оркестровки рабочего процесса и выполнения бизнес-логики. Любое типичное SWF-приложение имеет следующие строительные блоки:

AWS SWF - Процесс поддержки (3)
В терминах SWF рабочий процесс — это фактический шаблон, который описывает отдельные шаги, которые должен выполнить процесс. И выполнение рабочего процесса — это один запуск этого шаблона.
Стартер — процесс, который может запускать, останавливать и взаимодействовать с выполнением рабочего процесса.
Decider — процесс, который организует и решает, каков будет следующий шаг выполнения рабочего процесса.
Рабочий — процесс, который выполняет задачи определенного типа.
Консоль SWF — обеспечивает полную видимость и контроль исполнения.
Пример выполнения рабочего процесса может проходить через следующие шаги: стартер запускает выполнение рабочего процесса, SWF получает его, запрашивает решение о том, что является следующим шагом, а затем на основании решения передает задачу соответствующему работнику. Как только результат от рабочего работника получен, SWF снова запрашивает решение для следующего шага, и в зависимости от ответа может выполнить другой работник или нет. Этот поток продолжается до тех пор, пока решающее лицо не ответит, что рабочий процесс завершен. Вы можете увидеть, как решающий орган координирует каждый из этапов рабочего процесса, и рабочие действия выполняют отдельные задачи. Все это управляется SWF и проверяется на любом этапе.

Зачем использовать Camel?
Amazon предоставил клиентам Java работу, используя аннотации для генерации прокси-классов для доступа к службам SWF. Весь процесс генерации и использования прокси-классов в сочетании с зависимостью от стартера к решающему и от решающего к рабочим действиям не очень радостен. И что может быть лучше, чем использование маршрута Camel для оркестровки и другого маршрута для действующего рабочего? В результате появился компонент Camel SWF, который теперь находится в Camel Master. Компонент Camel-SWF имеет два типа конечных точек: рабочий процесс и активность .

Производитель рабочего процесса позволяет нам запускать, завершать, отменять, сигнализировать, получать состояние или извлекать всю историю выполнения рабочего процесса. На нашей диаграмме он представляет стартер. Вот пример того, как начать выполнение рабочего процесса:

1
2
3
4
from("direct:start")
    .setHeader(SWFConstants.OPERATION, constant("START"))
    .log("Starting a workflow task ${body}")
    .to("aws-swf://workflow?domainName=demo&workflowList=demo-flow&version=1.0&eventName=processWorkflows");

Потребитель рабочего процесса является решающим фактором. Он получает задачи решения от службы SWF и либо планирует задачи выполнения для выполнения, либо указывает, что выполнение рабочего процесса завершено. Это детерминистический маршрут без сохранения состояния, единственной задачей которого является организация задач:

1
2
3
4
from("aws-swf://workflow?domainName=demo&workflowList=demo-flow&version=1.0&eventName=processWorkflows")
    .log("Received a workflow task ${body}")
    .filter(header(SWFConstants.ACTION).isEqualTo(SWFConstants.EXECUTE_ACTION))
        .to("aws-swf://activity?domainName=demo&activityList=demo-activity&version=1.0&eventName=processActivities");

Конечные точки деятельности позволяют нам взаимодействовать с задачами деятельности. Производитель действий используется для планирования задач действий и может использоваться только с решающего маршрута (фактически с решающим потоком). Это потому, что только решающий может планировать задачи деятельности. Последнее поле в нашей диаграмме, которое мы должны предоставить для реализации, — это работник деятельности, который может быть создан с использованием потребителя деятельности. Эта конечная точка будет получать задания активности от SWF, выполнять их и возвращать результаты обратно в SWF. Это бит, который фактически выполняет бизнес-логику:

1
2
3
from("aws-swf://activity?domainName=demo&activityList=demo-activity&version=1.0&eventName=processActivities")
    .log("Received Activity task ${body}")
    .setBody(constant("1"));

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

Это не самый простой в использовании компонент, но он окупается простой и масштабируемой архитектурой.

PS: Спасибо моему бывшему менеджеру С. Уилеру за то, что он позволил мне внести этот компонент обратно в сообщество Camel.