Ключевые выводы
Взаимодействие на основе принципа «peer-to-peer» может привести к поведению системы, которое трудно понять разработчикам, операторам и бизнес-аналитикам.
Необходима полная видимость всех входящих и исходящих взаимодействий, происходящих при реализации бизнес-требования.
Решения, обеспечивающие обзор, варьируются от распределённого трейсинга, который, как правило, упускает бизнес‑перспективу; озер данных (data lakes), которые требуют определённых усилий для настройки под нужную информацию; process tracking, при котором необходимо заранее смоделировать процесс, чтобы можно было его отслеживать; process mining, который может обнаружить бизнес‑процесс; и вплоть до оркестрации, которая имеет встроенную видимость.
Мы утверждаем, что понимание, управление и изменение систем, построенных на микросервисной архитектуре, требует сбалансированного сочетания оркестрации и хореографии.
В прошлом году я встретил архитектора из крупной e‑commerce компании. Он рассказал, что они делают всё правильно: разделяют функциональность на небольшие части по границам доменов — даже если сами не называют такую архитектуру «микросервисной».
Затем мы обсудили, как эти сервисы взаимодействуют между собой, чтобы реализовать бизнес‑логику, пересекающую границы сервисов — ведь именно тут всё и начинается на практике. Он сказал, что их сервисы взаимодействуют через события, публикуемые в шину событий, что обычно называют «хореографией» (этот термин будет подробно разобран далее). Они считали это оптимальным решением с точки зрения слабой связанности.
Но проблема в том, что становится трудно понять, что вообще происходит, и ещё сложнее что-то изменить.
«Это не похоже на ту синхронную хореографию, которую показывают на слайдах в презентациях про микросервисы, — это неконтролируемое прыгание на месте!»
Это соответствует тому, что говорят и другие клиенты. Например, Джош Вулф из Credit Sense сказал:
«Система, которую мы заменяем, использует сложную peer-to-peer хореографию, и чтобы понять, что в ней происходит, приходится разбираться в нескольких кодовых базах одновременно».
Давайте подробнее рассмотрим это на упрощённом примере. Предположим, вы создаёте приложение для обработки заказов. Вы выбираете реализацию системы с использованием событийно-ориентированной архитектуры и, например, используете Apache Kafka как шину событий. Каждый раз, когда кто-то оформляет заказ, из сервиса оформления заказа отправляется событие, которое получает сервис оплаты. Этот сервис оплаты собирает деньги и отправляет событие, которое затем обрабатывается сервисом управления запасами.

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

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

Помните архитектуры, основанные на множестве триггеров в базе данных? Архитектуры, в которых ты никогда точно не знал, что произойдет, если сделать то или это — и вдруг — почему это случилось именно сейчас? Проблемы с реактивными микросервисами иногда немного напоминают мне это, хотя такое сравнение явно не совсем корректно.
Обеспечение видимости
Но что мы можем с этим сделать? Следующие подходы помогут вернуть видимость, однако у каждого из них есть свои плюсы и минусы:
Распределённый трейсинг (например, Zipkin или Jaeger)
Озёра данных или аналитические инструменты (например, Elastic)
Майнинг процессов (например, ProM)
Отслеживание с помощью автоматизации рабочих процессов (например, Camunda)
Имейте в виду, что все эти подходы наблюдают за работающей системой и анализируют проходящие через неё экземпляры. Мне неизвестны статические инструменты анализа, которые дают полезную информацию.
Распределенный трейсинг
Распределённый трейсинг предназначен для отслеживания цепочек вызовов между разными системами и сервисами. Для этого создаются уникальные идентификаторы трассировки, которые обычно добавляются в определённые заголовки (например, HTTP или заголовки сообщений) на общем уровне. Если все участники вашей системы понимают или хотя бы пересылают эти заголовки, вы можете оставлять «хлебные крошки» (breadcrumbs), пока запрос переходит от одного сервиса к другому.

Распределённый трейcинг обычно используется для понимания того, как запросы проходят через систему, для выявления сбоев или исследования причин узких мест в производительности. Преимущество распределённого трейcинга в том, что существует зрелый набор инструментов с активной экосистемой вокруг. Поэтому начать работу относительно просто, даже если обычно приходится (иногда достаточно инвазивно) внедрять специальные механизмы в ваши приложения или контейнеры.
Так почему же не использовать трейcинг, чтобы действительно понять, как бизнес-процессы формируются через события, проходящие через нашу систему? В основном, есть две причины, которые затрудняют применение распределённого трейcинга для этого сценария:
Трассировки сложно воспринимаются людьми без технического фона. Мои личные попытки показать результат трассировки нетехническим пользователям с треском провалились. Гораздо лучше было потратить немного времени и перерисовать ту же информацию в виде блоков и стрелок. И хотя данные о вызовах методов и передаче сообщений действительно полезны для анализа поведения взаимодействий, они слишком детализированы, чтобы уловить суть бизнес-процессов, проходящих через несколько сервисов.
Чтобы справиться с огромным объёмом таких детализированных данных, в распределённом трейсинге применяется так называемое семплирование — то есть собирается лишь небольшая часть всех запросов. Как правило, более 90% запросов вообще не записываются. Хорошую критику этого подхода можно найти в статье Three Pillars with Zero Answers — towards a New Scorecard for Observability. В итоге вы никогда не получаете полной картины происходящего.
Озёра данных и аналитические инструменты
Таким образом, стандартная трассировка «из коробки», скорее всего, не подойдёт. Логичным следующим шагом будет реализовать что-то похожее, но адаптированное под конкретную задачу. Речь идёт не о сборе технических трассировок, а о сборе значимых бизнес- или доменных событий, которые, возможно, уже и так циркулируют в вашей системе.
На практике это часто сводится к созданию сервиса, который будет слушать все события и сохранять их в хранилище, способное выдерживать нагрузку. В настоящее время многие наши клиенты используют для этого Elastic.

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

Один из недостатков — отсутствие визуального представления, которое помогло бы осмыслить список событий. Однако это можно встроить в инфраструктуру, например, проецируя события на визуализацию вроде BPMN.
Лёгкие фреймворки, такие как bpmn.io, позволяют добавлять информацию в такую диаграмму прямо на HTML-странице (пример можно найти [здесь]), и это также можно упаковать, например, в плагин для Kibana.

Эта модель не исполняется каким-либо движком бизнес-процессов — это диаграмма, предназначенная для визуализации зафиксированных событий другим способом. В этом смысле у вас есть определённая свобода в выборе уровня детализации, и вполне допустимо отображать события из разных микросервисов на одной диаграмме, ведь именно это вас и интересует — целостная картина.
Хорошая новость в том, что такая диаграмма не мешает вам вносить изменения в отдельные сервисы, то есть не ограничивает гибкость вашей организации. Однако обратной стороной является то, что диаграммы могут устаревать по сравнению с фактическим состоянием системы в продакшене.
Process Mining
В описанном выше подходе вы должны явно моделировать диаграмму, которую используете для визуализации. Но если характер потока событий заранее неизвестен, его сначала нужно выявить.
Такое обнаружение процессов может быть выполнено с помощью инструментов process mining (интеллектуального анализа процессов). Они позволяют вывести общую структуру процесса и представить её в виде графической модели — зачастую с возможностью глубокого анализа деталей, особенно в местах узких мест или потенциальных точек для оптимизации.

Звучит как идеальное решение для нашей задачи. К сожалению, такие инструменты чаще всего применяются для анализа процессов в наследованных (legacy) архитектурах, поэтому они в основном ориентированы на анализ логов, а не на работу с потоками событий в реальном времени.
Ещё одна проблема этих инструментов — они либо слишком научные и сложные в использовании (например, ProM), либо чересчур тяжеловесные (например, Celonis). Поэтому, по нашему опыту, внедрение таких инструментов в типичные микросервисные проекты часто оказывается непрактичным.

Тем не менее, обнаружение процессов и майнинг добавляют интересные возможности, позволяющие получить видимость ваших потоков событий и бизнес-процессов. Надеюсь, что вскоре появится технология с аналогичным функционалом, но при этом лёгкая, удобная для разработчиков и простая в освоении.
Отслеживание с помощью автоматизации воркфлоу
Ещё один интересный подход — моделировать рабочий процесс, а затем развертывать и запускать его на реальном движке рабочих процессов. Модель рабочего процесса особенная в том смысле, что она только отслеживает события и сама ничего активно не выполняет. То есть она не управляет процессом — она просто записывает события. Я рассказывал об этом на Kafka Summit в Сан-Франциско в 2018 году, а запись включает живую демонстрацию с использованием Apache Kafka и открытого движка рабочих процессов Zeebe.

Этот вариант особенно интересен, так как на рынке движков рабочих процессов происходит множество инноваций, что приводит к появлению инструментов, которые лёгкие, удобные для разработчиков и высокомасштабируемые. Я писал об этом в статье «Events, Flows and Long-Running Services: A Modern Approach to Workflow Automation». Очевидный недостаток в том, что модель рабочего процесса нужно создавать заранее. Но в отличие от мониторинга событий, эта модель выполняется на движке рабочих процессов — фактически вы запускаете экземпляры процесса для входящих событий или связываете события с соответствующим экземпляром. Это также позволяет выполнять проверки соответствия — соответствует ли реальность вашей модели?
Кроме того, такой подход позволяет использовать полный набор инструментов платформ автоматизации рабочих процессов, что даёт возможность видеть текущий статус, контролировать SLA, обнаруживать зависшие экземпляры и проводить детальный анализ исторических аудиторских данных.

Когда я проверял этот подход с клиентами, его было легко настроить. Нам просто нужно было создать универсальный компонент, который считывал события из шины и сопоставлял их с движком рабочих процессов. Каждый раз, когда событие не удавалось сопоставить, мы использовали небольшую таблицу решений, чтобы определить, можно ли его игнорировать или оно приведёт к инциденту, требующему последующей проверки. Мы также добавили инструменты в движки рабочих процессов, используемые внутри микросервисов для выполнения бизнес-логики, чтобы генерировать определённые события (например, запуск экземпляра процесса, его завершение или достижение контрольной точки) для использования в общей картине.
Это отслеживание рабочего процесса немного похоже на мониторинг событий, но с акцентом на бизнес-процесс. В отличие от трассировки, оно может записывать 100% ваших бизнес-событий и обеспечивать наглядное отображение, подходящее для различных заинтересованных сторон.
Взгляд со стороны бизнеса
Одним из больших преимуществ наличия бизнес-процесса в системе мониторинга является то, что вы понимаете контекст. Для конкретного экземпляра процесса вы всегда можете увидеть, как и почему он оказался в текущем состоянии, что позволяет понять, какой путь он не выбрал (но который часто выбирают другие экземпляры), а также какие события или данные привели к определённым решениям. Вы также можете получить представление о том, что может произойти в ближайшем будущем. Именно этого не хватает в других формах мониторинга. И даже если сегодня не очень модно обсуждать согласование бизнеса и ИТ, абсолютно необходимо, чтобы специалисты без инженерного образования тоже понимали бизнес-процессы и как события проходят через различные микросервисы.
Путь от отслеживания к управлению
Отслеживание процессов — это хорошо, так как оно обеспечивает операционный мониторинг, отчётность, ключевые показатели и видимость, являясь важным элементом для поддержания гибкости. Но в современных проектах такой подход к отслеживанию — всего лишь первый шаг на пути к более продуманному управлению и оркестрации в вашей микросервисной архитектуре.
Простой пример: вы начинаете отслеживать тайм-ауты для сквозного процесса. Как только тайм-аут срабатывает, автоматически предпринимается какое-то действие. В приведённом примере мы уведомляем клиента о задержке спустя 14 дней — но продолжаем ожидать. А через 21 день сдаёмся и отменяем заказ.

Интересный момент на приведённой выше схеме — отправка команды «отменить заказ». Это и есть оркестрация — и иногда вокруг неё ведутся спорные дискуссии.
Оркестрация
Я часто слышу, что оркестрацию следует избегать с аргументом, что она вводит связность или нарушает автономность отдельных микросервисов. И, конечно, верно, что оркестрацию можно реализовать плохо, но её также можно сделать так, чтобы она соответствовала принципам микросервисов и при этом приносила значительную пользу бизнесу. На конференции InfoQ New York 2018 я специально говорил об этом заблуждении.
По сути, для меня оркестрация означает, что один сервис может отдавать команду другому сделать что-то. Вот и всё. Это не более тесная связность, просто связность происходит в обратную сторону. Возьмём пример с заказом. Может быть хорошей идеей, если сервис оформления заказа просто генерирует событие о создании заказа, но не знает, кто его обрабатывает. Сервис заказов слушает это событие о создании заказа. Получатель знает о событии и решает, что с ним делать; связность находится на стороне получателя.
С платежами ситуация другая, потому что было бы довольно неестественно, если бы сервис платежей знал, для чего предназначен платёж. Но ему нужна эта информация, чтобы реагировать на нужные события, например, создание или оформление заказа. Это также означает, что сервис платежей придётся менять каждый раз, когда вы хотите принимать платежи за новые продукты или услуги. Во многих проектах обходят эту неудобную связность, генерируя события «требуется платеж», но это на самом деле не события, поскольку отправитель хочет, чтобы кто-то другой что-то сделал. Это команда! Сервис заказов отдаёт команду сервису платежей получить деньги. В этом случае отправитель знает о команде, которую нужно отправить, и решает её использовать; связность находится на стороне отправителя.
Любое взаимодействие между двумя сервисами подразумевает некоторую степень связности для эффективной работы, но в зависимости от конкретной задачи может быть более целесообразно реализовать связность на одной стороне, а не на другой.

Сервис заказов может даже отвечать за оркестрацию нескольких сервисов и отслеживание последовательности шагов в выполнении заказа. Я подробно обсуждал преимущества этого подхода в вышеупомянутом выступлении. Сложность заключается в том, что хорошая архитектура должна уметь балансировать между оркестрацией и хореографией, что не всегда просто.
Но в этой статье я хотел сосредоточиться на видимости процессов. И здесь очевидное преимущество оркестрации с использованием движка рабочих процессов: модель — это не только код для выполнения оркестрации, но и инструмент для непосредственного отображения и понимания потока.

Заключение
Очень важно обеспечить видимость ваших бизнес-процессов, независимо от того, как они реализованы. Я рассмотрел несколько вариантов, и в большинстве реальных ситуаций это обычно сводится к мониторингу событий с помощью инструментов наподобие Elastic или к отслеживанию процессов с использованием движков рабочих процессов. Это немного зависит от конкретного сценария и роли — бизнес-аналитикам необходимо понимать данные, собранные по всем экземплярам с нужной детализацией, тогда как операционная команда должна иметь возможность изучать отдельный экземпляр с разной степенью детализации и, вероятно, пользоваться инструментами для быстрого решения системных инцидентов.
Если у вас хореографический подход, отслеживание процессов может стать шагом к более широкой оркестрации, что, на мой взгляд, очень важно для долгосрочного контроля над бизнес-процессами. В противном случае, как говорит Мартин Фаулер, вы можете «создавать хорошо разделённые системы с уведомлениями о событиях, не осознавая, что теряете из виду более масштабный поток, и тем самым создаёте себе проблемы в будущем». Если вы работаете над новой системой с нуля, лучше сразу найти правильный баланс между оркестрацией и хореографией.
Однако, независимо от деталей реализации вашей системы, убедитесь, что у вас есть удобное для бизнеса представление о бизнес-процессах, реализуемых совместно работающими сервисами.
Об авторе
Бернд Рюкер (Bernd Ruecker) — сооснователь и технолог компании Camunda. Ранее он занимался автоматизацией масштабируемых ключевых рабочих процессов в таких мировых компаниях, как T-Mobile, Lufthansa и Zalando. В настоящее время он сосредоточен на новых парадигмах автоматизации рабочих процессов, которые вписываются в современные архитектуры, основанные на распределённых системах, микросервисах, предметно-ориентированном дизайне, событийно-ориентированной архитектуре и реактивных системах.

BPM Developers — про бизнес-процессы: новости, гайды, полезная информация и юмор.
olku
Реклама Камунды. После "попытки показать результат трассировки нетехническим пользователям с треском провалились" можно не читать. Графы вполне себе строятся и без BPMN нотаций.
stas_makarov Автор
графы разные бывают.
тут речь о смысле, а не о способе рисования.
покажите свои графы операционному директору и спросите, что он понял.
да, не факт, что он поймет ваши BPMN, но там хотя бы можно объяснить, раза со второго-третьего точно поймет.
а сырые данные трассировки как их ни визуализируй, все равоно непонятно будет
stas_makarov Автор
И почему реклама? Автор статьи - он же автор Камунды. О чем ему еще говорить? О российских импортозамещенных BPM? Было бы странно.
Это мнение из первых рук от разработчика продукта.
olku
Реклама потому, что альтернативы толком не рассматриваются. Ничего не имею против мнения разработчика продукта.
stas_makarov Автор
Реклама это когда что-то размещено за деньги.
Это чисто архитектурная статья. Замените движок на Flowable, Activiti, да хоть на ELMA - почти ничего не изменится.