Event-driven architecture (EDA) — архитектурный стиль, в котором компоненты системы общаются через события. Одно действие порождает событие, которое вызывает другие действия. Альтернатива синхронным запросам HTTP.
Принцип
- Producer (издатель) генерирует событие: "OrderCreated", "UserRegistered"
- Событие попадает в очередь/шину
- Consumers (подписчики) получают и обрабатывают
- Producer не знает, кто подписан, — только о самом факте события
Пример
Пользователь оформляет заказ:
- OrderService создаёт заказ → публикует OrderCreated
- InventoryService слушает → списывает товар
- PaymentService слушает → инициирует оплату
- NotificationService слушает → шлёт email
- AnalyticsService слушает → пишет в BI
Все параллельно, независимо.
Плюсы
- Слабая связанность (loose coupling)
- Масштабируемость: каждый consumer — независимо
- Устойчивость: падение одного consumer не валит систему
- Эволюция: можно добавлять новых подписчиков без правки producer
- Асинхронность: producer не ждёт обработки
Минусы
- Сложнее дебаг: где упало?
- Eventual consistency: данные не сразу синхронизированы
- Duplicate/ordering проблемы
- Схема событий — их версионирование
- Мониторинг сложнее
Инструменты
- Apache Kafka: лидер enterprise, умеет миллионы событий в секунду. LinkedIn, Netflix, Uber
- RabbitMQ: классический message broker. AMQP протокол
- AWS SQS/SNS: managed в облаке
- Google Pub/Sub
- Redis Streams: для более простых случаев
- NATS: лёгкий и быстрый
Kafka vs RabbitMQ
- Kafka: лог событий. Persistent, долгое хранение, можно "перевоспроизвести" события
- RabbitMQ: очередь с роутингом. Событие доставляется и пропадает. Гибкие маршруты
- Выбор: Kafka для event sourcing, аналитики, стриминга. RabbitMQ для задач, request/response
Event Sourcing
- Все изменения системы — серия событий
- Состояние получается проигрыванием событий
- Полная история: можно откатиться, аудит
- CQRS (Command Query Responsibility Segregation) — часто в паре
- Сложнее реализация, но мощно
Saga pattern
- Распределённая транзакция через события
- Каждый шаг — событие, компенсация при сбое
- Альтернатива 2-phase commit, который не работает в микросервисах
Idempotency
Обработчик события может получить его дважды. Нужно писать код, который не ломается от повтора. Использовать ключ идемпотентности.
Схемы и совместимость
- Schema Registry (Confluent): управление версиями схем
- Backward compatibility: новые поля не ломают старых
- Forward: старые клиенты игнорируют новые поля
- Protobuf, Avro — популярные форматы
Real-time стриминг
- Kafka Streams: обработка потоков
- Apache Flink: сложные аналитические запросы
- ksqlDB: SQL поверх Kafka
Observability
- Tracing: OpenTelemetry, Jaeger — отследить событие через все сервисы
- Metrics: Prometheus + Grafana
- Logging: централизованно в ELK/Loki
- Без этого — не отладить
Антипаттерны
- "Distributed monolith": сильная связность между событиями
- Синхронные вызовы замаскированные под события
- Чрезмерная гранулярность событий
- Отсутствие dead-letter queue для неудачных сообщений
Когда не стоит
- Простое CRUD-приложение
- Команда без опыта в распределённых системах
- Сильная потребность в транзакционной целостности
- Недостаточно мониторинга
Примеры
- Netflix: миллионы событий в секунду через Kafka
- Uber: каждое движение такси — событие
- LinkedIn: профили, уведомления, рекомендации через Kafka
- Российские: Ozon, Авито, Яндекс — все используют EDA
Есть вопрос?
Вопросы и ответы · 0
Не поняли что-то?
Зарегистрируйтесь — и сможете задать вопрос автору объяснения.
Загрузка комментариев…