Проекты, где Lambda дёргает Lambda напрямую через SDK — это связанность, хрупкость и сложность отладки. Когда появляется пятнадцатый потребитель того же события, приходится обновлять каждый источник. Event-Driven архитектура на серверлес решает это: компоненты общаются через события, а не прямые вызовы. Lambda функция не знает, кто ещё подписан на результат её работы. Это обеспечивает слабую связность, независимый масштаб и возможность добавлять новых потребителей без изменения источника. Наш опыт в десятках проектов подтверждает: такой подход в 3-5 раз ускоряет внедрение новых сервисов по сравнению с монолитным связыванием, а стоимость инфраструктуры снижается на 30-50% за счёт отказа от неиспользуемых ресурсов.
Почему Event-Driven, а не прямое связывание?
Прямые вызовы Lambda из Lambda (через SDK Invoke) создают жёсткие зависимости. Если процесс оплаты дёргает сервис доставки, а через месяц нужен фрод-фильтр, приходится править код оплаты. В event-driven модели каждый сервис публикует события, а новые потребители подписываются без изменений источника. Это радикально упрощает эволюцию системы и позволяет независимо деплоить компоненты.
По данным AWS, EventBridge обрабатывает свыше 4 трлн событий в месяц, обеспечивая задержку менее 100 мс.
Сравните: при прямых вызовах отказ одного звена рушит всю цепочку. EventBridge с SQS даёт гарантию доставки и автоматические ретраи — в 10 раз надёжнее, чем ручная обработка ошибок.
Архитектура на примере e-commerce
Обработка заказа без event-driven: PlaceOrder → ValidateInventory → ProcessPayment → SendEmail → UpdateAnalytics — всё последовательно, тесно связано.
С event-driven:
[Client] → PlaceOrder Lambda ↓ EventBridge: order.created / | \ ValidateInv SendEmail Analytics ↓ EventBridge: inventory.reserved ↓ ProcessPayment ↓ EventBridge: payment.processed / \ FulfillOrder SendReceipt Каждый сервис реагирует на события независимо. Новый сервис (например, fraud detection) подписывается на order.created без изменений существующего кода.
Как это работает на практике
AWS EventBridge: реализация
# Custom event bus + rule + target resource "aws_cloudwatch_event_bus" "orders" { name = "orders-bus" } resource "aws_cloudwatch_event_rule" "order_created" { name = "order-created" event_bus_name = aws_cloudwatch_event_bus.orders.name event_pattern = jsonencode({ "detail-type": ["OrderCreated"], "source": ["com.company.orders"] }) } resource "aws_cloudwatch_event_target" "process_inventory" { rule = aws_cloudwatch_event_rule.order_created.name event_bus_name = aws_cloudwatch_event_bus.orders.name arn = aws_lambda_function.validate_inventory.arn } Публикация события из Lambda:
import boto3 import json from datetime import datetime events = boto3.client('events') def publish_order_created(order: dict): events.put_events( Entries=[{ 'EventBusName': 'orders-bus', 'Source': 'com.company.orders', 'DetailType': 'OrderCreated', 'Detail': json.dumps({ 'orderId': order['id'], 'customerId': order['customer_id'], 'items': order['items'], 'totalAmount': order['total'], 'timestamp': datetime.utcnow().isoformat() }), 'Time': datetime.utcnow() }] ) SQS для надёжной доставки
EventBridge + SQS = отказоустойчивая доставка с retry и dead letter queue. Используем Terraform для инфраструктуры как кода:
resource "aws_sqs_queue" "inventory_updates" { name = "inventory-updates" visibility_timeout_seconds = 300 redrive_policy = jsonencode({ deadLetterTargetArn = aws_sqs_queue.inventory_dlq.arn maxReceiveCount = 3 # After 3 failures → DLQ }) } resource "aws_lambda_event_source_mapping" "inventory_processor" { event_source_arn = aws_sqs_queue.inventory_updates.arn function_name = aws_lambda_function.process_inventory.arn batch_size = 10 function_response_types = ["ReportBatchItemFailures"] } ReportBatchItemFailures — только неудачные сообщения возвращаются в очередь, успешные не повторяются.
Обработчик с partial failure
def handler(event, context): failed_message_ids = [] for record in event['Records']: try: process_message(json.loads(record['body'])) except Exception as e: # Только этот record пойдёт в retry, остальные — ОК failed_message_ids.append({'itemIdentifier': record['messageId']}) return {'batchItemFailures': failed_message_ids} Как обеспечить идемпотентность?
В event-driven системах события могут доставляться дважды (at-least-once delivery). Каждый обработчик должен быть идемпотентным. Используем DynamoDB как таблицу обработки с ConditionExpression:
import boto3 dynamodb = boto3.resource('dynamodb') processed_events = dynamodb.Table('processed_events') def handler(event, context): for record in event['Records']: event_id = record['messageId'] # Проверить, не обработано ли событие уже try: processed_events.put_item( Item={'event_id': event_id, 'ttl': int(time.time()) + 86400}, ConditionExpression='attribute_not_exists(event_id)' ) except processed_events.meta.client.exceptions.ConditionalCheckFailedException: continue # Already processed process_event(record) Процесс внедрения
Внедрение event-driven архитектуры под ключ включает этапы:
| Этап | Сроки |
|---|---|
| Проектирование event schema + шины | 2–3 дня |
| EventBridge настройка + правила маршрутизации | 2–3 дня |
| SQS + DLQ + Lambda event sources | 2–3 дня |
| Идемпотентность обработчиков | 2–4 дня |
| Distributed tracing + мониторинг | 2–3 дня |
| Интеграционное тестирование | 2–4 дня |
Все этапы могут выполняться параллельно для разных компонентов. Сроки зависят от сложности бизнес-логики и количества сервисов. Средний проект — 14 рабочих дней.
Сравнение: event-driven vs микросервисы на REST
Таблица сравнения
| Параметр | Event-Driven (AWS) | REST Микросервисы |
|---|---|---|
| Связанность | Слабая (через события) | Сильная (прямые вызовы) |
| Отказоустойчивость | Встроенные ретраи, DLQ | Ручная обработка, circuit breaker |
| Масштабирование | Независимое, per consumer | Требует синхронизации |
| Добавление нового сервиса | Подписка без изменений | Часто правка API gateway |
| Задержка | ~100 мс (EventBridge) | ~10 мс (прямой вызов) |
Мониторинг event-driven системы
Ключевые метрики:
- Event lag (SQS
ApproximateAgeOfOldestMessage) — насколько свежие события обрабатываются - DLQ depth — число событий в dead letter queue (ненулевое значение = проблема)
- Processing rate vs production rate — успевает ли система потреблять события
- End-to-end latency — время от события до результата через всю цепочку
Мы настраиваем CloudWatch alarms и дашборды, чтобы вовремя реагировать на отклонения. Опыт показывает: хороший мониторинг сокращает время реакции на инциденты в 2-3 раза.
Сколько времени занимает внедрение?
Сроки варьируются от 10 до 25 рабочих дней в зависимости от количества сервисов и сложности бизнес-логики. Оценка проекта бесплатна — пишите, мы подготовим детальный план и архитектурную схему.
Что входит в работу
Документация архитектуры и event schema, код Lambda-функций и инфраструктура как код (Terraform), настройка шин и очередей, реализация идемпотентности, мониторинг и алерты, тестовые скрипты, обучение команды. Мы даём гарантию на работоспособность решения в течение месяца после деплоя.
Закажите внедрение event-driven архитектуры — ваша система станет гибче и масштабируемее. Свяжитесь с нами для оценки вашего проекта, и мы подберём оптимальное решение.







