У попередніх лекціях ми познайомилися з Event-Driven Architecture (EDA) — подійно-орієнтованою архітектурою, її принципами та компонентами. Ми розібрали, як події створюють слабке звʼязування між мікросервісами, знижують залежність і покращують масштабованість. Ви дізналися, як працюють асинхронні комунікації, вивчили концепції producers і subscribers, а також зрозуміли, як message brokers, такі як Kafka, RabbitMQ і ActiveMQ, керують передачею даних. Також ми обговорили типові помилки при впровадженні EDA і кращі практики її проєктування.
Настав час застосувати теорію на практиці і спробувати спроєктувати подійно-орієнтовану архітектуру для конкретного кейсу.
Практичне проєктування подійно-орієнтованої архітектури
Постановка задачі: кейс "Магазин електронної комерції"
Уявіть, що вам потрібно розробити архітектуру подій для інтернет-магазину. Як головний архітектор системи, ви стикаєтеся з такими задачами:
- Опрацювання замовлень, включно з повідомленнями про статус замовлень, оплатою та доставкою.
- Автоматичне оновлення інформації про наявність товарів на складі.
- Відправка повідомлень користувачам про знижки на їх улюблені товари.
- Логування всіх подій для аналітики (наприклад, для побудови звітів).
Наша ціль — використати подійно-орієнтований підхід, щоб знизити звʼязаність сервісів і підвищити відмовостійкість.
Крок 1: Визначення подій
Перший крок — зрозуміти, які події відбуваються в системі. Подія — це така "новина" про те, що щось сталося. Наприклад:
| Подія | Опис |
|---|---|
OrderPlaced |
Замовлення створене користувачем |
OrderPaid |
Користувач оплатив замовлення |
OrderShipped |
Замовлення відправлено службою доставки |
InventoryUpdated |
Змінилася кількість товару на складі |
DiscountCreated |
Створено нову знижку, яка може зацікавити користувачів |
UserNotificationSent |
Повідомлення відправлено користувачу |
Кожна подія має свій payload і метадані, такі як час створення, ідентифікатор користувача тощо.
Крок 2: Ідентифікація producers і subscribers
Тепер, коли ми визначили події, потрібно зрозуміти, хто їх продукує (publishers) і хто на них реагує (subscribers).
| Подія | Видавець | Підписники |
|---|---|---|
OrderPlaced |
Order Service | Inventory Service, Payment Service |
OrderPaid |
Payment Service | Shipping Service, Notification Service |
OrderShipped |
Shipping Service | Notification Service |
InventoryUpdated |
Inventory Service | Analytics Service, Notification Service |
DiscountCreated |
Admin Service | Notification Service |
UserNotificationSent |
Notification Service | Analytics Service |
Приклад:
- Коли користувач створює замовлення,
Order Serviceпублікує подіюOrderPlaced. Цю подію обробляєInventory Service, щоб зменшити кількість товарів на складі, іPayment Service, щоб ініціювати процес оплати.
Крок 3: Створення схеми взаємодії
Давайте візуалізуємо, як сервіси обмінюються подіями. Ось схема, що показує взаємодію через message broker (наприклад, Apache Kafka):
User
↓
Order Service ──> OrderPlaced ─┬──> Inventory Service (зменшити склад)
└──> Payment Service (ініціювати оплату)
↓
Payment Service ──> OrderPaid ─┬──> Shipping Service (відправити замовлення)
└──> Notification Service (повідомити користувача)
↓
Shipping Service ──> OrderShipped → Notification Service
Крок 4: Визначення структури подій
Події мають містити корисну інформацію для підписників.
Приклад структури події OrderPlaced:
{
"eventId": "12345",
"eventType": "OrderPlaced",
"timestamp": "2023-10-01T12:34:56Z",
"payload": {
"orderId": "7890",
"userId": "456",
"orderItems": [
{
"productId": "101",
"quantity": 2
},
{
"productId": "202",
"quantity": 1
}
],
"totalPrice": 159.99
}
}
Подібні структури допомагають уніфікувати обробку подій, бо підписники завжди знають, чого очікувати.
Крок 5: Моделювання message broker
Для реалізації архітектури ми будемо використовувати Apache Kafka. Кожна подія публікуватиметься у свій topic.
| Топік | Тип події | Приклади повідомлень |
|---|---|---|
orders |
OrderPlaced |
Дані про створені замовлення |
payments |
OrderPaid |
Дані про успішні оплати |
shipping |
OrderShipped |
Дані про відправлені замовлення |
inventory |
InventoryUpdated |
Дані про зміну залишків на складі |
notifications |
UserNotificationSent |
Дані про відправлені повідомлення |
Вправа: реалізація producer і consumer для події OrderPlaced
Реалізація producer:
// Producer для відправки події OrderPlaced у Kafka
@Component
public class OrderEventProducer {
private final KafkaTemplate<String, String> kafkaTemplate;
public OrderEventProducer(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void sendOrderPlacedEvent(String orderId, String eventPayload) {
kafkaTemplate.send("orders", orderId, eventPayload);
System.out.println("Подія OrderPlaced відправлена: " + eventPayload);
}
}
Реалізація підписника:
// Consumer для обробки події OrderPlaced
@Component
@KafkaListener(topics = "orders", groupId = "inventory-service")
public class OrderEventConsumer {
@Autowired
private InventoryService inventoryService;
@KafkaHandler
public void handleOrderPlacedEvent(String message) {
System.out.println("Отримано подію OrderPlaced: " + message);
inventoryService.updateInventory(message);
}
}
Поради з проєктування подійно-орієнтованої архітектури
- Мінімізуйте залежності. Кожен сервіс має бути максимально ізольований. Наприклад,
Notification Serviceне має знати внутрішню логікуOrder Service. - Логируйте події. Це допоможе відстежити, що відбувається в системі, особливо в асинхронній обробці.
- Ідентифікуйте схеми подій. Використовуйте JSON Schema, щоб всі події дотримувалися чіткого формату.
- Забезпечте узгодженість. Якщо подію не оброблено, її можна повторити завдяки механізму Kafka's "At least once".
Підсумкова вправа
Для закріплення знань спроєктуйте подійно-орієнтовану архітектуру для системи бронювання авіаквитків. Визначте ключові події (FlightBooked, PaymentProcessed, TicketIssued), їх видавців і підписників. Опишіть взаємодію сервісів і створіть схему подій.
Ось і все! Тепер ви практично опанували основи проєктування подійно-орієнтованої архітектури. Попереду — ще більше EDA і асинхронної магії.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ