Общая структура MessageQueue
Как с легкостью заменить реализацию очереди сообщений в крупномасштабных проектах?
Очереди сообщений играют важную роль в крупномасштабных решениях, поскольку проект становится все более и более сложным - добавляются микросервисы, и мы становимся зависимыми от функциональности очереди сообщений.
Однажды мы просыпаемся и обнаруживаем, что текущая реализация очереди сообщений не отвечает нашим меняющимся потребностям, мы меняем ее - и попадаем в бесконечный цикл рефакторинга и регрессионных тестов.
Итак, можем ли мы разработать структуру, которая позволит нам изменить реализацию, не затрагивая весь проект?
В этом посте я хотел бы поделиться с вами структурой, которая позволяет это сделать, как я разработал в последнем проекте отличного курса Продвинутое проектирование систем Продвинутое системное проектирование Дэна Гиттика в Тель-Авивском университете.
Этот пост станет первым в серии, в которой я поделюсь с вами некоторыми гибкими, но НАДЕЖНЫМИ и надежными решениями проблем проектирования.
Отделение очереди сообщений от ее реализации
Самая важная цель фреймворка - дать нам возможность легко изменить реализацию очереди сообщений (то есть RabbitMQ на Kafka).
Мы хотим, чтобы такое изменение было дружественным и требовало минимального изменения кода, а проверка архитектурных спецификаций была бы понятна и для некодеров.
Итак, мы создали файл конфигурации - просто подключи и работай!
Такой файл конфигурации описывает, как создать очередь сообщений для каждой микрослужбы:
- Издатели (которые позволяют нам отправлять сообщения в очередь сообщений)
- Потребители (которые позволяют нам получать сообщения из очереди сообщений)
Структура файла конфигурации будет следующей:
Издатели и потребители описывают поля, необходимые для создания их конкретной реализации (например, конкретный обмен издателем / потребителем RabbitMQ), рецепты этих полей называются «Контекст».
ПРИМЕЧАНИЕ. Это пример файла конфигурации YAML, но это может быть любой файл со словарной структурой, как я реализовал в проекте.
ПРИМЕЧАНИЕ. Пример файла конфигурации RabbitMQ MessageQueue, доступного здесь.
Использование контекста MessageQueue в платформе
Итак, мы создали файл конфигурации, теперь мы можем - в зависимости от типа микросервиса - загружать его издателей и потребителей, используя поля, которые мы называем «Контекст».
Мы бы реализовали фабрику, загружающую файл конфигурации; получает тип микросервиса и создает соответствующие ему объекты контекста.
Такой объект контекста будет содержать все соответствующие поля для реализации и обязательно содержит информацию о его роли (издатель или потребитель).
С точки зрения пользователя фреймворка, мы хотели бы иметь возможность запускать издателей и потребителей микросервисов на основе загруженных объектов контекста.
Итак, давайте представим, как все это сочетается:
Вот как работает поток:
- Используя фабрику MessageQueue, мы создаем объект Context.
- Контекст, используемый для инициализации MessageQueuePublisher или MessageQueueConsumer.
- MessageQueuePublisher и MessageQueueConsumer вызывают модуль, который загружает конкретную реализацию (например, RabbitMQMessageQueue) на основе выбранного типа MessageQueue (может быть настроен как переменная среды). Эта реализация принимает объект Context и инициализируется как Издатель или Потребитель.
Поэтому, когда мы хотим изменить тип реализации MessageQueue, мы просто:
- Создайте файл конфигурации
- Создайте класс, который наследуется от абстрактного класса MessageQueue, и реализуйте методы для инициализации из контекста, публикации и потребления (например, RabbitMQ).
ПРИМЕЧАНИЕ! Посмотреть пример инициализации можно в Микросервисе парсера.
… До следующего поста!
Понравилась эта статья? Не стесняйтесь удерживать нажатой кнопку 👏 под 😀