В сегодняшнем скоротечном мире, когда коммуникация и скорость передачи сообщений играют невероятно важную роль, того же мы хотим от больших технологических систем. Нам нужно, чтобы приложения или сервисы общались в режиме реального времени, и передача сообщений занимала миллисекунды. Эту задачу решает среди прочего построение архитектуры системы с использованием шины данных (message bus). Шина данных – это специфический тип инфраструктуры, позволяющий разным системам (или компонентам системы) коммуницировать, используя определенный общий интерфейс, а сама шина выступает своего рода посредником между ними. Это очень эффективный и надежный способ обмена данными между системами, который к тому же очень хорошо масштабируется, чему обязан своей популярностью. Кроме того, в отличие от других типов 'communication architectures' (например, клиент-сервер или peer-to-peer), шина данных, являясь своего рода «брокером» для обмена сообщениями между системами, позволяет не устанавливать тесные связи между сервисами или приложениями, что делает систему существенно более гибкой.
Что нужно знать для эффективной работы с шиной данных
Собственно принцип работы шины данных
В системе будут те компоненты или сервисы, которые будут публиковать данные на шину, назовем их отправителями (senders), и читающие эти сообщения – получатели или потребители (receivers/consumers). Для большей структурированности и удобства обычно у каждого компонента будет свой «кусочек» на шине данных, называемый очередью сообщений (message queue/ service queue). Абстрактно это что-то вроде почтового ящика определенного абонента. Каждое сообщение, отправляемое на шину данных, будет иметь свою тему (topic), имеющую определенную структуру. Компоненты системы, являющиеся потребителями данных (условно – ждут конкретных сообщений, чтобы совершить определенные действия с ними), будут подписываться на эти темы/топики, чтобы получать их сразу в момент публикации.
Пример:
Есть несколько компонентов системы трейдинга. Один мы называем «диспетчером», его задача – забирать все новые заказы клиентов, форматировать их должным образом и публиковать их как сообщения на шину данных по теме ХХХ/YYY/ZZZ/E/NEWO, где
XXX – код системы/приложения
YYY – код подсистемы
ZZZ – код енвайрмента, в котором произошло событие (ведь их несколько)
E – event (тип события)
NEWO – new order (название события)
Второй компонент, назовем его «адаптером», имеет свою очередь сообщений и подписан на указанную выше тему. Как только публикуется новое сообщение по такой теме, оно попадает в очередь сообщений адаптера. А задача адаптера – добавить к данным, содержащимся в заказе клиента, внутренние данные компании, необходимые для его обработки, и опубликовать снова на шину данных с темой ХХХ/YYY/ZZZ/E/NEWO/ACTIVE.
В свою очередь, на тему ХХХ/YYY/ZZZ/E/NEWO/ACTIVE подписаны еще два компонента – «персистор», который будет хранить новые заказы в базу данных (переводя в необходимый формат), и OMS система, которая будет дальше обрабатывать заказ.
Очень часто системы, построенные таким образом, называют событийными(event-based): есть определенное событие – оно в виде сообщения публикуется на шине данных, а другие компоненты ее подхватывают и совершают определенные действия. Также такие системы чаще всего построены с использованием микросерирсов. Помимо вышеприведенного примера, это может быть отдельный микросервис, который в определенный момент читает данные клиентов из базы данных, переводит в нужный формат и публикует сообщения на шину данных. Задача другого микросервиса будет исключительно забирать эти сообщения, валидировать в отношении данных с CRM, дополнять их, например, данными об имеющихся у каждого клиента средствах, и снова публиковать на шину. Третий микросервис будет разрешать или отклонять попытку логина каждого клиента в систему, сравнивая введенные данные с этими сообщениями из шины данных. И так далее.
Json та xml
Здесь нет ничего сложного или особенного, но следует и нужно понимать как читать эти форматы. Для эффективной работы шины данных все публикуемые на нее сообщения имеют определенную структуру, и любое отклонение от нее будет вызывать проблемы. Чаще данные будут описаны в формате json.
Пример события с данными клиента
{
“type”: EventType_Customer”,
“header”: {
“eventID”: “124nf;sdkgjp5849”,
“type”: “EvtType_EVENT”,
“subtype”: “EvtSubType_CUSTOMER_EVENT”,
“timestamp”: “1716984729186”},
“customer”: {
“Contact”: [{
“ContactID”: “1234567”,
“ContactName”: “John Smith”,
“Role”: “trader”,
“Default”: true}]
“LegalEntity”: {
“LegalEntityID”: “87655341”,
“LegalEntityName”: “Trading Company Ltd.”,
“LocationCode”: “LDN”,
“CountryCode”: “UK”,
“Tradeable”: true
}
}
}
Уметь читать логи
Это то, чему пришлось мне учиться, когда я попала на текущий проект. Ведь полноценное понимание системы, с которой я работаю, по сути, означает основательное понимание всех потоков данных между компонентами. Кто, что и в каком формате публикует на шину данных, кто из нее читает и что должно происходить дальше. Это все я могу отследить в логах каждого компонента системы. К примеру, клиент отправляет заказ с UI, куда он попадает? Как выглядит? Какой компонент должен его валидировать? Какой принять/согласовать? Что происходит дальше до момента, когда заказ можно считать успешным (или не успешным).
Помимо собственно логов, мы используем несколько инструментов для просмотра контента собственно самой шины данных по каждому отправителю или каждому топику.
Знать архитектуру (и дружить с архитектором)
Собственно, подытоживая вышесказанное – чтобы описать любое новое функциональное или нефункциональное требование, нужно четко понимать, как все в деталях работает сейчас.
Что это все означает для бизнес-аналитика
Существенно больше деталей, начиная со сбора требований
По крайней мере, по сравнению с моими предыдущими проектами. При сборе требований кроме работы со стандартным набором стейкхолдеров надо всегда учитывать поток данных. То есть, в критериях приемки для какой-то банальной истории типа логина будет еще формат и структура сообщения, которое должно отправиться на шину данных, топик, куда это должно публиковаться, а затем будет еще прорисован дополнительный поток сообщений – какие компоненты будут на него подписаны и что далее с ним делать (включая отрицательные сценарии типа публикации неполного сообщения). А если это совершенно новое требование, которое соответственно будет генерировать совершенно новое событие/сообщение – это нужно еще согласовать с архитекторами, ведь одна шина данных может использоваться множеством аппликейшней и сервисов, и ваш новый ивент должен быть корректно добавлен в общую структуру и ничего не сломать .
UML и другие инструменты
В текущем проекте архитекторы используют диаграмму классов для хранения модели событий всей шины данных, но уверены, что есть другие и лучшие способы. В данном случае у нас каждое событие/сообщение – это объект в диаграмме классов, а все необходимые элементы (части контента) – это атрибуты, и все это будет сочетаться рядом ассоциаций.
А для сбора требований и построения архитектуры для новых комплексных фич неоднократно хорошо себя показал метод event storming. Он как раз позволяет визуально показать поток данных между всеми участниками процесса, проанализировать разные возможные сценарии развития событий и запланировать какие микросервисы могут решить поставленные задачи.
Для визуализации взаимодействия компонентов в рамках определенного процесса используем диаграмму последовательности (sequence diagram).
Пример работы с требованиями:
Представим, мы хотим разработать новую фичу – дать нашим клиентам возможность менять заказ после размещения. Очевидно, что мы укажем все типовые функциональные критерии относительно того, кто именно может изменять, в какой промежуток времени может изменять, как это будет происходить на UI, какие возможны ограничения при изменении и т.д. Но к нефункциональным требованиям мы должны добавить также требования по потоку данных.
Обычно я прописываю эти требования по следующему условному темплейту:
Черновая структура события/сообщения, которое будет отправляться на шину данных (на примере существующих событий даю свои предложения относительно того, как будет выглядеть сообщение в формате json)
Модель данных. В диаграмме классов раскладываю это сообщение на атрибуты и прописываю возможные варианты значений для каждого из них. В данном примере, поскольку у нас существует событие для созданного заказа, и одним из атрибутов заказа является статус - Active - мы можем просто добавить к существующей модели данных новый статус - Amend, а остальное можно переиспользовать.
(видим, что событие OrderEvt является одним из подвидов более общего события Event. Как любой ивент в системе должно иметь три ID (eventID, lastID, ClientID), которые его определяют. OrderEvt имеет также несколько атрибутов:
OrderState, который может принимать значение New, Active, Amended (который мы добавляем в рамках требований, над которыми работаем, Deleted, Closed)
Customer, который в свою очередь будет иметь перечень собственных атрибутов
OrderType, который может принимать одно из трех существующих значений (Type1, Type2, Type3 )
Product, который также может принимать одно из трех существующих значений.)
Предложенный топик, под которым эти события будут публиковаться на шину данных. В нашем примере, если мы имели топик ХХХ/YYY/ZZZ/E/NEWO/ACTIVE для новых активных заказов, вероятно изменения будут публиковаться под топиком ХХХ/YYY/ZZZ/E/NEWO/AMEND.
Перечень компонентов или сервисов, которые будут подписаны на этот топик. В данном случае, например, тот самый персистор, который обновит базу данных соответствующим образом, и OMS система, которая будет дальше обрабатывать заказы
Поток данных (сообщение опубликовали на шину данных, что происходит дальше?). Чаще всего в виде диаграммы последовательности, ведь в данном случае очень важна последовательность событий. Для простого примера покажем, что заказ отправляется нам с фронтенда, попадает на шину данных, откуда его «забирает» какой-то проверяющий его микросервис «адаптер», добавляет к нему данные, возвращает на шину в статусе Active, а оттуда его считывает опять же наша UI (показывает клиенту, что заказ теперь активен).
Дополнительные требования к работе системы с этими данными. В данном случае условно скажем, что система должна при получении такого сообщения добавить оригинальный заказ в архив и не обрабатывать его, а обрабатывать измененное, используя тот же флоу, который используется для нового заказа.
Конечно, все эти детали при работе над требованиями и рефайнментом сессий обсуждаются, согласовываются и корректируются с командой разработки и архитекторами.
Документация, документация, документация
Учитывая первый пункт относительно большого количества деталей – все должно быть записано: структура и примеры сообщений, модель данных, пошаговые флоу каждого происходящего события (потоки данных, сервисы, пользующиеся этими данными, топики, в которые публикуются данные). Если у вас есть доступ к логам или другим инструментам отслеживания потока данных в вашей системе, хорошо иметь под рукой реальные примеры передачи сообщений между системами или компонентами систем (положительные сценарии – как выглядит успешный флоу, и отрицательные – когда в системе случаются ошибки из-за сбоев в передаче данных) или структуре данных). Все должно быть сохранено и доступно в удобном с точки зрения навигации формате.
Поддержка куа и команды сопровождения
Ввиду высокого уровня детализации при сборе и описании требований, БА становится важным центром знания о платформе. Поэтому очень часто меня зовут помочь найти причины ошибки, которую поймала команда сапорта или QA во время тестирования.
В целом, как видим, работа по message bus предполагает основательную работу с данными, что означает умение работать как с разными форматами данных, так и с различными инструментами визуализации этих данных, а также несколько более техническое и глубокое погружение в построение системы.
Если вы хотите углубить свои технически знания, обратите внимание на тренинги Technical skillsfor Business Analyst и Advanced Technical skills for Business Analyst
Comments