Общая структура MessageQueue

Как с легкостью заменить реализацию очереди сообщений в крупномасштабных проектах?

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

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

Итак, можем ли мы разработать структуру, которая позволит нам изменить реализацию, не затрагивая весь проект?

В этом посте я хотел бы поделиться с вами структурой, которая позволяет это сделать, как я разработал в последнем проекте отличного курса Продвинутое проектирование систем Продвинутое системное проектирование Дэна Гиттика в Тель-Авивском университете.

Этот пост станет первым в серии, в которой я поделюсь с вами некоторыми гибкими, но НАДЕЖНЫМИ и надежными решениями проблем проектирования.

Отделение очереди сообщений от ее реализации

Самая важная цель фреймворка - дать нам возможность легко изменить реализацию очереди сообщений (то есть RabbitMQ на Kafka).

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

Итак, мы создали файл конфигурации - просто подключи и работай!

Такой файл конфигурации описывает, как создать очередь сообщений для каждой микрослужбы:

  • Издатели (которые позволяют нам отправлять сообщения в очередь сообщений)
  • Потребители (которые позволяют нам получать сообщения из очереди сообщений)

Структура файла конфигурации будет следующей:

Издатели и потребители описывают поля, необходимые для создания их конкретной реализации (например, конкретный обмен издателем / потребителем RabbitMQ), рецепты этих полей называются «Контекст».

ПРИМЕЧАНИЕ. Это пример файла конфигурации YAML, но это может быть любой файл со словарной структурой, как я реализовал в проекте.

ПРИМЕЧАНИЕ. Пример файла конфигурации RabbitMQ MessageQueue, доступного здесь.

Использование контекста MessageQueue в платформе

Итак, мы создали файл конфигурации, теперь мы можем - в зависимости от типа микросервиса - загружать его издателей и потребителей, используя поля, которые мы называем «Контекст».

Мы бы реализовали фабрику, загружающую файл конфигурации; получает тип микросервиса и создает соответствующие ему объекты контекста.

Такой объект контекста будет содержать все соответствующие поля для реализации и обязательно содержит информацию о его роли (издатель или потребитель).

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

Итак, давайте представим, как все это сочетается:

Вот как работает поток:

  1. Используя фабрику MessageQueue, мы создаем объект Context.
  2. Контекст, используемый для инициализации MessageQueuePublisher или MessageQueueConsumer.
  3. MessageQueuePublisher и MessageQueueConsumer вызывают модуль, который загружает конкретную реализацию (например, RabbitMQMessageQueue) на основе выбранного типа MessageQueue (может быть настроен как переменная среды). Эта реализация принимает объект Context и инициализируется как Издатель или Потребитель.

Поэтому, когда мы хотим изменить тип реализации MessageQueue, мы просто:

  • Создайте файл конфигурации
  • Создайте класс, который наследуется от абстрактного класса MessageQueue, и реализуйте методы для инициализации из контекста, публикации и потребления (например, RabbitMQ).

ПРИМЕЧАНИЕ! Посмотреть пример инициализации можно в Микросервисе парсера.

… До следующего поста!

Понравилась эта статья? Не стесняйтесь удерживать нажатой кнопку 👏 под 😀