- PVSM.RU - https://www.pvsm.ru -
Возможно, ваша компания захочет перейти на архитектуру микросервисов и автоматизировать рабочие процессы (в этом посте блога я не вдаюсь в мотивацию, но вы, возможно, захотите прочитать о 5 Workflow Automation Use Cases You Might Not Have Considered [1] или BizDevOps — the true value proposition of workflow engines [2]). Это ставит вас в ряд со многими нашими клиентами [3]. Как правило, у вас возникнут вопросы:
В этой записи блога я даю некоторые рекомендации по основным архитектурным решениям, которые вам необходимо принять. Я дам упрощенные советы, чтобы помочь вам начать ориентироваться в этой сложной теме.
Так как вся теория такая теория, то я хочу обсудить определенные аспекты на конкретном бизнес-примере, который легко понять и следовать за ним. Я последовательно рассмотрю следующие аспекты:
Пример, который я использую в этой статье, представляет собой простое приложение для выполнения заказа, доступное в виде flowing-retail примера приложения [7] с исходным кодом на GitHub. Самое интересное в программе flowing-retail то, что она реализует различные архитектурные альтернативы и предоставляет примеры на разных языках программирования. Все примеры используют движок рабочего процесса, будь то Camunda BPM [8] или Zeebe [9]. Но вы можете перенести полученные знания на другие инструменты — я просто знаю инструменты из своей собственной компании лучше всего, и у меня есть много примеров кода, которые легко доступны.
Предположим, вы хотите реализовать некоторые бизнес-возможности (например, выполнение заказа при нажатии кнопки тире на Amazon [10]) с помощью разделенных сервисов.
Один из первых вопросов, как правило, касается оркестровки или хореографии, при этом последний чаще всего рассматривается как лучший вариант (на основе статьи «Microservices» Martin Fowler [11]). Обычно это сочетается с Event-driven архитектурой [12].
В такой хореографической архитектуре вы излучаете так называемые доменные события, и каждый заинтересованный может действовать в соответствии с этими событиями. Это трансляция. Идея заключается в том, что вы можете просто добавлять новые микросервисы, которые прослушивают события, ничего больше не меняя. Рабочий процесс как таковой нигде не является явным, но развивается как цепочка событий, которые передаются по кругу. Опасность заключается в том, что вы теряете из виду более масштабный поток [13], в нашем примере выполнение заказа. Становится невероятно трудно понять поток, изменить его или также управлять им. И даже ответы на такие вопросы, как «Есть ли какие-либо заказы просрочены?» или «Есть ли что-нибудь застрял, что нуждается в вмешательстве?» является проблемой. Я обсуждаю это в своем докладе Complex event flows in distributed systems (записанные, например, в QCon в Нью-Йорке [14] или DevConf в Кракове [15]).
Вы можете найти рабочий пример чистой хореографии здесь: https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/choreography-alternative [16]
Легким решением может быть, по крайней мере, отслеживание потока событий. В зависимости от конкретной технической архитектуры (см. ниже), вы, вероятно, можете просто добавить движок рабочего процесса, считывающий все события и проверяющий, могут ли они быть соотнесены с потоком отслеживания. Я обсуждал это в своем докладе Monitoring and Orchestration of Your Microservices Landscape with Kafka and Zeebe [17] (запись с Kafka Summit в Сан-Франциско [18]).
Это неинвазивно, так как вам не нужно ничего менять в своей архитектуре. Но это позволяет вам начать что-то делать, например в случае задержки заказа:
Обычно это приводит к переходу от простого отслеживания потока к его реальному управлению:
Хорошая архитектура обычно представляет собой смесь хореографии и оркестровки. Справедливости ради надо сказать, что нелегко уравновесить эти две силы, не имея определенного опыта. Но мы видели много доказательств того, что это правильный путь, поэтому определенно стоит инвестировать время. Иначе ваша хореография, которая на доске была изящным танцем независимых профессионалов, обычно заканчивается скорее беспорядочным слэмом:
В flowing-retail примере это также означает, что у вас должен быть отдельный микросервис для наиболее важной бизнес-возможности: заказа клиента!
Но как настроить архитектуру с помощью движка рабочего процесса для достижения такого баланса? Давайте упростим дело и предположим, что мы начинаем с нуля, и мы можем выбрать только из трех альтернатив архитектуры (так что никаких гибридных архитектур или наследия не будет).
Мы пока не рассматриваем, следует ли запускать движок рабочего процесса централизованно или децентрализованно, что является отдельным вопросом, за него мы возьмёмся позже.
Эта архитектура основана на центральной шине для асинхронной связи. К этой шине подключаются различные микросервисы. Логика оркестровки и соответствующие потоки оркестровки принадлежат микросервисам. Рабочие процессы могут посылать на шину новые команды («эй оплата, пожалуйста, найди деньги для меня») или ждут, пока произойдут события («кто бы ни заинтересовался, я получил оплату за O42»).
В этой архитектуре вы просто активно вызываете другие микросервисы, чаще всего синхронно, с блокировкой. Самый известный способ сделать это — REST. Конечные точки обычно извлекаются из реестра. Движок рабочего процесса может организовать вызовы REST, а также помочь с проблемами удаленной связи — тему, которую я подробно обсуждал в моей статье о трех проблемах интеграции микросервисов [26] (также доступной в виде выступления [27], записанной, например, на QCon London [28]).
В этой архитектуре рабочий процесс распределяет работу между микросервисами, что означает, что он сам становится своего рода шиной. Микросервисы могут подписаться на определенную работу рабочего процесса и получать задачи через некую очередь.
Как всегда сложно дать четкую рекомендацию. Обычно я пытаюсь выяснить, что уже устоялось в компании, и основываю свое решение на интуиции относительно того, что может быть успешным в этой среде.
Например, если у клиента нет опыта работы с Kafka или Messaging, будет очень сложно заложить это на ходу. Поэтому, возможно, им лучше использовать архитектуру на основе REST, особенно если, например, они глубоко погрузились в Spring Boot, что делает некоторые проблемы относительно легко решаемыми. Однако, если они стратегически хотят двигаться в сторону большей асинхронности, я лично поддерживаю это, но я все же хочу убедиться, что они действительно могут справиться с этим. Если заказчик уже принимает Domain-driven design (DDD) [36] и события, или даже использует такие фреймворки, как Akka или Axon, то событийный подход, включающий в себя движок рабочего процесса, может быть лучшим вариантом.
Таким образом, существует широкий спектр возможностей, и я думаю, что все варианты могут быть полностью действенными. Спросите себя, что подходит вашей организации, какие инструменты у вас уже есть и какие цели вы преследуете. Не забудьте о своих разработчиках, которым приходится выполнять всю тяжелую работу и которые должны по-настоящему понимать, что они делают. И не забывайте об операционной деятельности, чтобы быть уверенным, что вам действительно будет весело, когда вы выйдете в продакшн.
Если вы хотите использовать движок рабочего процесса для распределения работы, он должен быть централизованным. В других альтернативах у вас есть два с половиной варианта:
Хорошим предварительным чтением по этому поводу будет Architecture options to run a workflow engine [37].
В микросервисах по умолчанию дают командам большую автономию и максимально изолируют их друг от друга. В этом смысле, по умолчанию подразумеваются децентрализованные движки, по одному рабочему движку на каждый микросервис, которому он нужен. Каждая команда может даже решить, какой именно движок (продукт) они хотят использовать.
Обычно в этой архитектуре больше всего обсуждается мониторинг: «Как мы можем следить за тем, что происходит»?
Чаще всего наличие децентрализованных операционных инструментов является преимуществом. Поскольку команды в микросервисных архитектурах часто выполняют DevOps для запускаемых ими служб, они несут ответственность за исправление ошибок в рабочих процессах. Поэтому довольно здорово, что у них есть сфокусированный взгляд, в котором они видят только то, за что отвечают.
Но часто вы все же хотите иметь общий обзор, по крайней мере, сквозных потоков, пересекающих границы микросервисов. В настоящее время клиенты часто создают собственный централизованный мониторинг, чаще всего на основе, например, Elastic. Теперь вы можете отправлять самые важные события из децентрализованных движков (например, запуск экземпляра рабочего процесса, достижение контрольной точки, сбой или завершение экземпляра рабочего процесса). Централизованный мониторинг просто показывает обзор на более высоком уровне и подробно связывает с децентрализованными операционными инструментами. Другими словами, децентрализованный движок рабочего процесса обрабатывает всю логику повторных попыток и обработки сбоев, а центральный мониторинг просто дает видимость всего потока.
В нашем собственном стеке мы начинаем допускать определенные инструменты для сбора данных из децентрализованных движков, например, Camunda Optimize [39] или Zeebe Operate.
Для упрощения операций можно также запустить центральный движок. Это удаленный ресурс, к которому микросервисы могут подключаться для развертывания и выполнения рабочих процессов. Технически это может быть через REST (Camunda BPM) или gRPC (Zeebe).
Если вы хотите использовать движок рабочего процесса в качестве распределителя, вам, конечно же, необходимо запустить его централизованно.
Такой подход обычно нуждается в некотором объяснении. Что вы можете сделать в Camunda, так это запустить движок рабочего процесса в виде библиотеки (например, используя Spring Boot Starter [42]) децентрализованным образом в различных микросервисах. Но затем вы подключаете все эти движки к центральной базе данных, где они встречаются. Это позволяет бесплатно осуществлять централизованный мониторинг.
Я лично предпочитаю децентрализованный подход в целом. Он просто совпадает с сутью и ценностью микросервисов.
Но я рад запустить центральный движок если есть веские доводы. Это особенно актуально для небольших компаний, где накладные расходы имеют большее значение, чем четкие границы коммуникации. Это также уменьшают проблему окна обслуживания движка рабочего процесса. Итак, практическое правило: чем крупнее компания, тем больше вы должны стремиться к децентрализации. Вдобавок к организационным причинам, нагрузка на движок также поможет определиться — поскольку несколько движков также означает распределение нагрузки.
Наличие гибрида с общей базой данных — изящный трюк, возможный с Camunda, но, наверное, не стоит злоупотреблять. Я бы ограничил это сценарием, где вы все еще можете контролировать все случаи использования движка рабочего процесса, и легко обсуждать их с каждой командой, использующей его.
Конечно, вы также можете смешивать и сочетать. Например, вы можете поделиться одной базой данных между ограниченным количеством микросервисов, которые каким-то образом связаны, но другие команды используют полностью разделенный движок.
Однако, гораздо более важным вопросом, чем вопрос о том, где работает сам движок, является вопрос о владении и управлении моделями процессов.
Независимо от физического развертывания модели рабочего процесса (читай: где работает движок) должно быть предельно ясно, кто отвечает за определенную модель, где она поддерживается и как вносятся изменения.
В микросервисных архитектурах право собственности на модель рабочего процесса должно принадлежать команде, владеющей соответствующей областью.
В примере flowing-retail есть две модели рабочего процесса:
Очень важно, чтобы вы распределяли право собственности на части бизнес-процесса в соответствии с границами вашей области. Не создавайте монолит BPM [5] — например, где процесс выполнения заказа обрабатывает бизнес-логику и другие детали, связанные с оплатой — просто потому, что вы используете модель рабочего процесса.
Меня часто спрашивают: Но где же «процесс оркестровки»? Это просто: в моем понимании микросервиса, нет такого понятия, как «процесс оркестровки».
Часто люди имеют в виду сквозные бизнес-процессы, как, например, выполнение заказа в приведенном выше примере. Конечно, сквозной процесс очень заметен и важен, но это логика области, как и все остальное, и переходит в границы микросервиса, в нашем примере — микросервиса заказа. В этом смысле микросервис заказа, содержащий логику сквозной оркестровки, может быть очень важным — но организованным так же, как и другие микросервисы, например, оплата.
Говоря «процесс оркестровки», некоторые люди имеют в виду логику области, которая включает только поток, поэтому соответствующий микросервис может не иметь другой логики (без собственных данных, без собственного программного кода,…). Это нормально, но это должен быть микросервис, поскольку даже эта логика требует четких обязанностей. И часто логика со временем все равно растет.
Описанная тема сложна, и здесь нет простых ответов для всех сценариев. Надеюсь, этот пост дал вам некоторую ориентацию. Подведем итоги:
Вам нужно выбрать стиль коммуникации: Асинхронный, RPC-связь или распределение работы с помощью движка рабочего процесса. В зависимости от этого выбора движок рабочего процесса может оказать вам различные услуги:
Право собственности на модели рабочего процесса должно находиться в компетенции соответствующего микросервиса. Рабочий процесс должен быть четко сконцентрирован на этой области.
Вы можете запустить движок рабочего процесса централизованно или децентрализованно.
Отслеживать или управлять — вы должны стремиться к сбалансированному сочетанию хореографии и оркестровки.
Автор: Диана Рахманова
Источник [45]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/mikroservisy/356920
Ссылки в тексте:
[1] 5 Workflow Automation Use Cases You Might Not Have Considered: https://thenewstack.io/5-workflow-automation-use-cases-you-might-not-have-considered/
[2] BizDevOps — the true value proposition of workflow engines: https://blog.bernd-ruecker.com/bizdevops-the-true-value-proposition-of-workflow-engines-f342509ba8bb
[3] нашими клиентами: https://camunda.com/case-studies/
[4] разраниченный контекст: https://martinfowler.com/bliki/BoundedContext.html
[5] Avoiding the «BPM monolith» when using bounded contexts: https://blog.bernd-ruecker.com/avoiding-the-bpm-monolith-when-using-bounded-contexts-d86be6308d8
[6] Real-Life BPMN: https://www.amazon.com/Real-Life-BPMN-introductions-CMMN-DMN/dp/1541163443/
[7] flowing-retail примера приложения: https://github.com/berndruecker/flowing-retail
[8] Camunda BPM: https://camunda.com/
[9] Zeebe: https://zeebe.io/
[10] кнопки тире на Amazon: https://en.wikipedia.org/wiki/Amazon_Dash
[11] на основе статьи «Microservices» Martin Fowler: https://martinfowler.com/articles/microservices.html
[12] Event-driven архитектурой: https://en.wikipedia.org/wiki/Event-driven_architecture
[13] что вы теряете из виду более масштабный поток: https://martinfowler.com/articles/201701-event-driven.html
[14] в QCon в Нью-Йорке: https://www.infoq.com/presentations/event-flow-distributed-systems/
[15] DevConf в Кракове: https://www.youtube.com/watch?v=EegrVoPTRbQ
[16] https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/choreography-alternative: https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/choreography-alternative
[17] Monitoring and Orchestration of Your Microservices Landscape with Kafka and Zeebe: https://www.slideshare.net/BerndRuecker/kafka-summit-2018-monitoring-and-orchestration-of-your-microservices-landscape-with-zeebe
[18] запись с Kafka Summit в Сан-Франциско: https://www.confluent.io/kafka-summit-sf18/the_big_picture/
[19] паттернов интеграции предприятия: https://www.enterpriseintegrationpatterns.com/
[20] агрегатор: https://www.enterpriseintegrationpatterns.com/patterns/messaging/Aggregator.html
[21] повторный упорядочитель: https://www.enterpriseintegrationpatterns.com/patterns/messaging/Resequencer.html
[22] Saga pattern: https://blog.bernd-ruecker.com/saga-how-to-implement-complex-business-transactions-without-two-phase-commit-e00aa41a1b1b
[23] «Lost in transaction»: https://www.slideshare.net/BerndRuecker/2018-lost-in-transaction/
[24] записано, например, на JavaZone Oslo: https://2018.javazone.no/program/45df84d4-e819-4fc9-9e3b-931972891441
[25] https://github.com/berndruecker/flowing-retail/tree/master/kafka/java: https://github.com/berndruecker/flowing-retail/tree/master/kafka/java
[26] о трех проблемах интеграции микросервисов: https://www.infoworld.com/article/3254777/3-common-pitfalls-of-microservices-integrationand-how-to-avoid-them.html
[27] доступной в виде выступления: https://www.slideshare.net/BerndRuecker/3-common-pitfalls-in-microservice-integration
[28] на QCon London: https://www.youtube.com/watch?v=O2-NHptllKQ&feature=youtu.be
[29] https://www.rabbitmq.com/tutorials/tutorial-six-java.html: https://www.rabbitmq.com/tutorials/tutorial-six-java.html
[30] паттерны устойчивости (например, повторные попытки): https://blog.bernd-ruecker.com/fail-fast-is-not-enough-84645d6864d3
[31] https://github.com/berndruecker/flowing-retail/tree/master/rest: https://github.com/berndruecker/flowing-retail/tree/master/rest
[32] Circuit Breaker: https://martinfowler.com/bliki/CircuitBreaker.html
[33] External Tasks: https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/
[34] Workers: https://docs.zeebe.io/basics/job-workers.html
[35] https://github.com/berndruecker/flowing-retail/tree/master/zeebe: https://github.com/berndruecker/flowing-retail/tree/master/zeebe
[36] Domain-driven design (DDD): https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
[37] Architecture options to run a workflow engine: https://blog.bernd-ruecker.com/architecture-options-to-run-a-workflow-engine-6c2419902d91
[38] https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/order-camunda: https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/order-camunda
[39] Camunda Optimize: https://camunda.com/products/camunda-bpm/optimize/
[40] https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/monitor: https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/monitor
[41] https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/order-zeebe: https://github.com/berndruecker/flowing-retail/tree/master/kafka/java/order-zeebe
[42] Spring Boot Starter: https://docs.camunda.org/manual/latest/user-guide/spring-boot-integration/
[43] Rolling Upgrade: https://docs.camunda.org/manual/latest/update/rolling-update/
[44] Deployment Aware Process Engine: https://docs.camunda.org/manual/latest/user-guide/process-engine/the-job-executor/#job-execution-in-heterogeneous-clusters
[45] Источник: https://habr.com/ru/post/518872/?utm_source=habrahabr&utm_medium=rss&utm_campaign=518872
Нажмите здесь для печати.