Frog Proger 19 сентября 2024

🏗️ 3 основных шаблона событийно-ориентированной архитектуры

Создание масштабируемых систем – непростая задача. Но с помощью трех ключевых шаблонов событийно-ориентированной архитектуры вы сможете строить системы, готовые к росту и изменениям.
🏗️ 3 основных шаблона событийно-ориентированной архитектуры
Этот материал взят из нашей еженедельной email-рассылки, посвященной бэкенду. Подпишитесь, чтобы быть в числе первых, кто получит дайджест.

Знание шаблонов событийно-ориентированной архитектуры позволяет:

  • Создавать слабосвязанные системы, в которых сбой одного компонента не приводит к полному отказу всей системы, а составные части приложения легче масштабировать и модифицировать.
  • Эффективно управлять асинхронными операциями и обрабатывать непредсказуемые события в системе.
  • Разрабатывать отзывчивые и эффективные приложения, обрабатывающие данные в реальном времени.
  • Создавать высоконагруженные системы, в которых требуется быстрая реакция на события.
  • Эффективно использовать современные технологии, например потоковую обработку данных и бессерверные вычисления.

Шаблон конкурирующих потребителей

Шаблон конкурирующих потребителей используется для эффективного распределения большого количества асинхронных сообщений между несколькими потребителями.

Competing Consumer Pattern оптимально распределяет нагрузку между несколькими потребителями и обеспечивает отказоустойчивость системы обработки сообщений
Competing Consumer Pattern оптимально распределяет нагрузку между несколькими потребителями и обеспечивает отказоустойчивость системы обработки сообщений
***

🚀 Внимание, джедаи кода!

Пришло время освоить силу шаблонов проектирования!

🎮 Обучайтесь, создавая легендарную игру «Звездные войны»!

С 18 по 25 сентября действует космическая акция: -30% на курс «Архитектуры и шаблоны проектирования» по промокоду MIDDLE.

🔥 Что вас ждет:

  • Погружение в мир профессионального проектирования
  • Практические навыки на реальном проекте
  • Создание собственной игры по мотивам «Звездных войн»
***

Основные компоненты и принцип работы этого паттерна выглядят так:

Производители сообщений

  • Один или несколько производителей отправляют сообщения в очередь.
  • Эти сообщения представляют собой задачи, которые нужно выполнить.

Очередь сообщений

  • Все сообщения попадают в одну централизованную очередь.

Потребители

  • Настраивается несколько экземпляров потребителей.
  • Каждый потребитель способен обрабатывать сообщения из очереди.

Конкуренция за сообщения

  • Потребители соревнуются друг с другом за получение и обработку сообщений.
  • Когда потребитель успешно получает сообщение, оно становится недоступным для других потребителей.

Обработка и удаление

  • После обработки сообщения потребитель подтверждает его получение.
  • Обработанное сообщение удаляется из очереди.

Ключевой момент в этом шаблоне – необходимость обработки каждого сообщения только одним потребителем. Разные инструменты и платформы решают эту задачу по-своему:

RabbitMQ использует предварительную выборку:

  • Потребители устанавливают лимит на количество неподтвержденных сообщений.
  • Полученное сообщение учитывается в полете и не доставляется другим потребителям.

Azure Service Bus применяет механизм peek-lock (просмотр и блокировка):

  • Потребитель получает сообщение в режиме peek-lock, что блокирует сообщение.
  • Сообщение остается в очереди, но становится невидимым для других потребителей.
  • После обработки потребитель помечает сообщение как завершенное.

AWS SQS устанавливает тайм-аут видимости:

  • При получении сообщения потребителем, SQS устанавливает тайм-аут видимости.
  • В течение этого времени сообщение скрыто от других потребителей.
  • После обработки потребитель удаляет сообщение.
  • Если тайм-аут истекает до удаления, сообщение снова становится видимым для других.

Шаблон повторных попыток сообщений

Шаблон повторных попыток сообщений используется для обработки ошибок при работе с очередями сообщений. Этот шаблон позволяет создать надежную систему обработки транзакций, способную справляться с временными сбоями и обеспечивающую контролируемый процесс для работы с проблемными транзакциями, например, при обработке платежей.

Retry Messages Pattern обеспечивает повторную обработку неудачных транзакций
Retry Messages Pattern обеспечивает повторную обработку неудачных транзакций

Основные компоненты паттерна и их функции:

  • Основная очередь – сюда поступают новые транзакции для обработки.
  • Очередь мертвых писем (Dead Letter Queue, DLQ) – отдельная очередь для сообщений, которые не удалось обработать после нескольких попыток.
  • Очередь повторных попыток (опционально) – ее можно использовать для планирования повторных попыток с задержкой.

Компоненты шаблона взаимодействуют так:

Потребитель (например, процессор платежей) берет сообщение из основной очереди и пытается обработать транзакцию. Если обработка не удалась:

  • Проверяется счетчик попыток (обычно хранится в метаданных сообщения).
  • Если счетчик меньше максимального числа попыток, то счетчик увеличивается, а сообщение возвращается в очередь (с задержкой или без).
  • Если счетчик больше или равен максимальному числу попыток – сообщение перемещается в DLQ.

Паттерн позволяет использовать 2 стратегии повторных попыток:

  • Можно возвращать сообщения напрямую в основную очередь с задержкой.
  • Или использовать отдельную очередь повторных попыток с триггером по времени.

Обработка мертвых сообщений DLQ:

  • Необходимо мониторить DLQ для сообщений, исчерпавших попытки обработки.
  • Реализовать процесс для работы с такими сообщениями (например, ручная обработка).

При реализации этого паттерна стоит следовать следующим лучшим практикам:

  • Экспоненциальная задержка – нужно увеличивать интервал между попытками экспоненциально, чтобы не перегружать систему.
  • Идемпотентность – необходимо обеспечить безопасность повторной обработки платежа без риска двойного списания.
  • Время жизни сообщения – нужно установить общее время жизни для сообщений, чтобы предотвратить обработку очень старых транзакций.
  • Лимиты повторных попыток – установить максимальное число попыток обработки.
  • Типы ошибок – надо различать временные ошибки (можно повторить) и постоянные ошибки (сразу отправлять в DLQ).

Шаблон асинхронного запроса-ответа

Шаблон асинхронного запроса-ответа позволяет создавать масштабируемые и устойчивые к сбоям системы, где сервисы могут взаимодействовать асинхронно, не блокируя друг друга и сохраняя способность корректно обрабатывать ответы даже при изменении состояния системы между запросом и ответом.

Async Request-Response Pattern используется для организации взаимодействия между сервисами в асинхронном режиме, особенно полезен для длительных операций
Async Request-Response Pattern используется для организации взаимодействия между сервисами в асинхронном режиме, особенно полезен для длительных операций

Проблемы, которые решает шаблон:

  • В синхронном REST API один экземпляр запрашивающего сервиса всегда связан с одним экземпляром отвечающего сервиса.
  • В асинхронной модели экземпляр, отправивший запрос, может быть недоступен к моменту получения ответа.
  • Необходимо правильно соотнести запросы и ответы при наличии множества экземпляров сервисов.

Оптимальное решение этих проблем – использование корреляционного ID, уникального идентификатора, который связывает запрос и соответствующий ему ответ. При наличии такого ID организовать процесс работы (на примере показанного выше взаимодействия Сервиса заказов и Платежного сервиса) можно так:

1. Клиент размещает заказ через экземпляр.

2. Сервис заказов:

2.1 Генерирует уникальный корреляционный ID для этого заказа.

2.2. Сохраняет данные заказа и корреляционный ID в базе данных, распределенном кэше или локальной хэш-таблице.

2.3. Отправляет запрос на оплату в очередь запросов вместе с корреляционным ID.

3. Платежный сервис:

3.1 Получает запрос на оплату из очереди.

3.2 Обрабатывает платеж.

3.3. Отправляет ответ в очередь ответов, включая тот же корреляционный ID.

4. Сервис заказов (тот же или другой экземпляр):

4.1. Получает ответ из очереди ответов.

4.2. Использует корреляционный ID для сопоставления ответа с исходным запросом заказа.

4.3. Выполняет необходимые действия (например, подтверждение заказа).

💻 Библиотека программиста
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека программиста»

Преимущества использования корреляционного ID:

  • Позволяет отправлять несколько запросов на оплату для одного заказа (повторные попытки, частичные платежи и т.д.).
  • Разделяет логику маршрутизации и бизнес-контекст (например, ID заказа).
  • Облегчает отслеживание потока запроса через несколько сервисов.

Важные аспекты, которые необходимо учесть при реализации шаблона:

  • Хранение контекста – надо сохранять информацию о запросе и корреляционном ID.
  • Обработка таймаутов – нужно предусмотреть механизм обработки ситуаций, когда ответ не приходит в ожидаемое время.
  • Идемпотентность – важно обеспечить корректную обработку повторных ответов.
***

Есть ли у вас опыт применения этих шаблонов в реальных проектах?

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ