Event-Driven Architecture Vocabulary: Event Storming, CQRS, Saga Pattern, and More (англійською)
Повний посібник щодо словникового запасу архітектури з керуванням подією: події домену, пошук подій, CQRS, шаблони saga, хореографія проти оркестрації, реєстр схем і CloudEvents. Для інженерів сервера, системних архітекторів і розробників, які створюють розподілені системи з керуванням подією.
Архітектура, керована подією (EDA) є фундаментальним шаблоном дизайну для сучасних розподілених систем, що використовуються в мікросервісах, конвеєрах реального часу і інтеграції підприємств. Проте її словниковий запас дуже багатий: події домену, команди, саги, хореографія, CQRS, пошук подій, еволюція схем.
Якщо ви приєднаєтеся до інженерної команди, яка працює з Kafka, RabbitMQ, EventBridge або будь- якою іншою системою, що керується подіями, вам слід точно володіти цим словником. Цей посібник охоплює 45 найважливіших термінів.
Що таке архітектура, що керується подією?
** Архітектура, керована подією (EDA) ** — це шаблон проектування, за якого компоненти спілкуються за допомогою створення і використання ** подій ** — сповіщень про те, що щось сталося — замість того, щоб викликати один одного безпосередньо.
Властивості ключа:
- Слабке з’єднання — виробники не знають, хто споживає їхні події
- ** Асинхронний ** — виробник не чекає, поки споживач закінчить
- ** Масштабований ** — споживачі можуть масштабувати незалежно від виробників
“Ми перейшли від синхронних викликів REST між мікросервісами до архітектури, керованої подією - тепер платіжна служба просто видає подію
PaymentCompletedі не потрібно знати про запаси, доставку або очки лояльності.”
Основний словник: події, команди, повідомлення
Подія домену
** Подія домену ** — це запис, що щось важливе сталося у бізнес- домені. Події називаються у ** минулому часі ** і описують факт, а не запит.
Добрі назви подій: OrderPlaced, PaymentFailed, UserRegistered, InventoryDepleted
Неправильні назви подій: PlaceOrder, ProcessPayment ← це команди, а не події
“Ми випускаємо подію домену
OrderShipped, коли склад підтверджує відправку — нижні системи (повідомлення, аналітика, лояльність) реагують на це незалежно.”
Command
Команда — це повідомлення, яке вказує службі щось зробити. Команди називаються в імперативі: PlaceOrder, SendEmail, ProcessRefund. Команда може бути прийнята або відхилена — її можна відкинути.
** Ключова відмінність від подій: **
- ** Подія **: * “X відбулося” * — минуле, факт, не можна скасувати
- ** Команда **: * « Будь ласка, виконайте X » * — імператив, запит, може закінчитися невдачею або бути відхилено
Message
** Повідомлення ** — це загальний термін для будь- яких даних, що надсилаються між системами — це може бути подія, команда або результат запиту. Події і команди — це спеціалізовані типи повідомлень.
Пам’ятник-бюст / І
** Конверт події ** обгортає вміст події метаданими: ідентифікатором події, типом події, штампом часу, службою джерела, версією схеми. Відокремлення метаданих від вантажу полегшує маршрутизацію і ведення журналу.
Типовий конверт:
{
"id": "evt_9823hf",
"type": "order.placed",
"source": "order-service",
"time": "2026-04-08T10:00:00Z",
"data": { "orderId": "123", "amount": 99.99 }
}
Специфікація CloudEvents
** CloudEvents ** — це специфікація CNCF для опису даних подій у спільному, незалежному від виробника форматі. Визначає стандартний набір атрибутів конверта: id, source, type, datacontenttype, time тощо
“Ми стандартизували на CloudEvents, тому нашим споживачам подій не потрібен нетиповий аналіз для кожного виробника — конверт завжди має той же формат.”
Інцидент штурм
Інцидент штурм
** Підтримка подій ** — це метод спільної роботи (винайдений Альберто Брандоліні), за допомогою якого група людей з різних галузей знань розробляє бізнес- процес, розміщуючи на стіні кольорові листівки:
- 🟠 Помаранчевий: події домену
- 🔵 Blue: команди
- 🟡 Жовтий: актори (які запускають команду)
- 🟣 ** Пурпурний **: правила / бізнес- правила (коли подія X → запускає команду Y)
- 🟩 ** Зелений **: зовнішні системи
- 🔷 ** Блакитний **: читання моделей (перегляд/запит системних потреб)
“Перед написанням будь-якого коду, ми провели дводенний семінар з власником продукту, експертами з домену та інженерами — ми виявили 30 доменів подій, які ми не розглядали, і знайшли, де наші обмежені контексти повинні бути.”
Aggregate
У випадку штурму подій і проектування на основі домену, ** агрегат ** є кластером пов’ язаних об’ єктів, які розглядаються як єдина одиниця для змін даних. Події зазвичай випромінюють агрегати.
Policy
У режимі штурму подій ** правила ** (показано фіолетовим) представляють бізнес- правило, яке реагує на подію і запускає команду: * « Якщо [домен події] тоді [команда] » *.
Приклад: “Якщо OrderPlaced тоді ReserveInventory “
Читання моделі
** Модель читання ** — це спеціалізований, попередньо обчислений перегляд даних, оптимізований для запитів, відрізняється від моделі запису. У CQRS і пошуку подій, моделі читання будуються за допомогою споживання подій.
Походження подій
Походження подій
** Визначення джерела події ** — це шаблон тривалості, за якого стан об’ єкта визначається за допомогою повторення послідовності подій, а не безпосереднього зберігання поточного стану.
Замість:
UPDATE orders SET status = 'shipped' WHERE id = 123;
Ви зберігаєте:
Event: OrderPlaced → timestamp: 10:00
Event: PaymentTaken → timestamp: 10:05
Event: OrderShipped → timestamp: 14:00
Поточний стан обчислюється за допомогою повторення всіх подій з початку.
- “Ми використовуємо пошук подій для агрегування замовлень — ми можемо відтворити точний стан будь- якого замовлення в будь- який момент часу, відтворюючи його історію подій.” *
Історія магазину
** Склад подій ** — це база даних, створена спеціально для зберігання подій у режимі, який дозволяє лише додавати події. На відміну від звичайної бази даних, ви ніколи не оновлюватимете або не вилучатимете події — ви лише додаватимете нові. EventStoreDB, Apache Kafka (як довговічний журнал) і нестандартні реалізації є поширеними.
Projection
** Проекція ** (або ** Проекція подій **) це процес, який споживає події зі сховища подій і створює модель читання. Проекції можна відновити, відтворюючи всі події з початку.
“Наша панель аналітики є проекцією — вона споживає всі
OrderPlacedіPaymentCompletedподії і створює агреговану статистику продажів.”
Повторення події
** Повторення події ** застосовує всі збережені події з початку для відтворення стану або проекцій. Використовується після виправлення помилок, для нових проектів або для перенесення.
CQRS (Command Query Responsibility Segregation) — розділення відповідальності за запит
CQRS
** Розділення відповідальності за запит команди (CQRS) ** — це шаблон, який відокремлює модель ** запису ** (команди, що змінюють стан) від моделі ** читання ** (запити, що повертають стан). Часто поєднується з пошуком подій.
- ** Командний бік **: обробка змін стану, надсилання подій
- ** Сторона запиту **: створює оптимізовані моделі читання з подій
“Наш каталог продуктів використовує CQRS — сторона запису обробляє складні оновлення запасів і видає події; сторона читання підтримує денормалізований індекс ElasticSearch, оптимізований для пошуку.”
Командний автобус
** Командна шина ** — це компонент, який маршрутизує команди до їх обробників. Команди надсилаються, один обробник обробляє кожну команду, і, за бажанням, у результаті обробки надсилається подія.
Послідовність можлива
** Неперервність після події ** означає, що після обробки команди і надсилання події модель читання буде оновлено * з часом *, а не відразу. Буде показано коротке вікно, у якому буде показано, що моделі запису і читання не синхронізовані.
“Після того, як користувач оновив свій профіль, модель читання оновлюється протягом 50-200 мс — вона зрештою стає послідовною. Ми показуємо користувачеві їх оновлені дані негайно з моделі запису, щоб уникнути плутанини.”
Пам’ятний знак
Saga
** Saga ** це шаблон для керування довготривалими транзакціями у декількох службах, де кожен крок є локальною транзакцією, а кожна помилка має компенсаційну транзакцію, щоб скасувати її.
Sagas замінюють розподілені ACID транзакції (які часто недоступні в мікросервісах) послідовністю слабко сполучених кроків.
Хореографічна саги
У ** сазі хореографії ** кожна служба реагує на події, що відбуваються у попередній службі. Немає центрального координатора — служби є автономними і реагують на потік подій.
Приклад потоку — Order Saga (хореографія):
OrderService → emits OrderCreated
→ PaymentService reacts → emits PaymentProcessed
→ InventoryService reacts → emits InventoryReserved
→ ShippingService reacts → emits OrderShipped
Переваги: вільне з’єднання, немає однієї точки несправності Недоліки: важко відстежувати стан глобальної сати, зневадження складне
Оркестрація-заснована Saga
У ** saga orchestration ** центральний ** saga orchestrator ** надсилає команди до кожної служби і очікує відповідей/ подій, перш ніж переходити до наступного кроку.
** Приклад потоку (оркестрація): **
SagaOrchestrator → commands PaymentService
SagaOrchestrator ← receives PaymentCompleted
SagaOrchestrator → commands InventoryService
...
Переваги: просте перегляду стану глобальної сати, простіше зневадження Недоліки: оркестратор є однією точкою з’ єднання
“Ми обрали оркестрацію, а не хореографію, тому що наша сага має 8 кроків і умовні гілки — явний оркестратор робить поток зрозумілим і перевіряним.”
Компенсація транзакції
** компенсуюча операція ** — це операція скасування для кроку з цієї серії — виконується, якщо пізніший крок з цієї серії зазнає невдачі. Кожен крок у сазі має мати компенсаційну операцію.
Приклад: Якщо ShipOrder зазнає невдачі після успішного ChargePayment, компенсуюча транзакція буде RefundPayment.
Кількість мертвих листів (DLQ)
Черга мертвих листів — це черга повідомлень, які неможливо обробити — після повторних спроб, отруйних повідомлень, невідповідностей у схемах або застарілої TTL. Необхідно для діагностики і відновлення невдалої обробки подій.
Повідомлення брокерів
Topic
У Kafka і подібних системах, ** тема ** є названим, тривалим журналом подій. Продюсери пишуть на теми; споживачі читають з них. Теми є основним організаційним підрозділом.
Partition
Розділ Kafka ** розділ ** є підрозділом теми. Повідомлення у розділі впорядковані. Розділи дозволяють паралельність — декілька користувачів можуть обробляти різні розділи одночасно.
“Тема
ordersмає 50 розділів — наші 50 клієнтських екземплярів мають по одному розділу, обробляють замовлення паралельно.”
Конкурентна група
** група споживачів ** це набір споживачів, які спільно споживають тему — кожне повідомлення у розділі буде доставлено саме одному споживачеві у групі. Дозволяє горизонтально масштабувати споживання.
Принаймні один раз. Одноразова доставка
- ** At-least-once **: повідомлення може бути доставлено більше ніж один раз (консуматори з безпекою повторних спроб повинні бути idempotent)
- ** Точно- один раз **: повідомлення буде доставлено точнісінько один раз (це складно досягти, зазвичай, за допомогою операцій Kafka або за додаткову плату)
“Ми використовуємо принаймні одну доставку і робимо всіх наших споживачів ідемпотентними — обробка тієї ж події двічі дає той же результат.”
Ідентифікація споживача
Ідемобільний споживач може безпечно обробляти одне і те ж повідомлення кілька разів без дублювання побічних ефектів. Критично для систем, що доставляють принаймні один раз.
Схема реєстру та схеми Evolution
Схема реєстру
** Реєстр схем ** є централізованим сховищем схем подій — зберігає визначення кожного типу подій і забезпечує сумісність схем під час створення або використання подій.
Популярні реалізації: Confluent Schema Registry, AWS Glue Schema Registry.
Схеми Avro / Protobuf
** Avro ** і ** Protobuf ** — це двійкові формати серіалізації, які зазвичай використовуються з регістрами схем. Вони більш компактні і включають підтримку еволюції схеми в порівнянні з JSON.
Схема еволюції
** Еволюція схеми ** змінює схему подій з плином часу без руйнування існуючих споживачів. Існує три режими сумісності:
- ** Зворотньо сумісна **: нова схема може читати дані, записані старою схемою (додати необов’ язкові поля)
- ** Сумісний з наступними версіями **: стара схема може читати дані, записані новою схемою (вилучіть необов’ язкові поля)
- ** Повністю сумісний **: працює в обох напрямках
“Перед публікацією нової події
OrderPlacedз додатковим полемcouponCode, ми перевірили, що вона є зворотньо сумісною — існуючі споживачі, які не знають проcouponCode, все ще будуть працювати.”
Схема зміни (англ.)
** Розривна зміна ** в схемі подій є зміною, яка робить існуючих споживачів нездатними десеріалізувати нові події - наприклад, вилучення необхідного поля або зміна типу поля. Розрив змін вимагає версійних скачок і скоординованої міграції.
Ключові фрази
| Situation | Phrase |
|---|---|
| Choosing choreography vs. orchestration | ”For simple flows, choreography keeps services decoupled. For complex multi-step sagas, orchestration gives better visibility and control.” |
| Explaining eventual consistency | ”After the command is processed, the read model will be updated within milliseconds — it’s eventually consistent, not immediately consistent.” |
| Describing event sourcing | ”We store every state change as an event — we can reconstruct the full history of any order at any point in time.” |
| Discussing schema evolution | ”The new field is optional and backward compatible — existing consumers don’t need to be updated.” |
| Explaining a DLQ | ”Failed events go to the dead letter queue — we monitor it daily and replay events once we’ve fixed the consumer bug.” |