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

Весь представленный код доступен на Github. Да вы можете легко получить к нему доступ через раздел «Полезные ресурсы» в конце статьи.

# Показатель

  1. Объяснение архитектуры
  2. Что такое Кафка?
  3. Практический пример
  4. Заключение
  5. Полезные ресурсы

# Объяснение архитектуры

Как вы, возможно, уже знаете, связывание сервисов - это то, чего мы всегда должны избегать. В противном случае любое внесенное изменение окажет значительное влияние на другие службы.

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

  • Архитектура, управляемая событиями (EDA)
  • Архитектура, управляемая сообщениями (MDA)

Что нового в этих паттернах? Концепция использования сообщений для передачи событий, которые представляют изменения в состоянии.

Чтобы быстро добавить новые функции в ваше приложение, вашей службе нужно только начать прослушивание потока событий / сообщений, отправленных другой службой.

Лучший пример, который я всегда приводил, - это обновление кеша памяти.

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

При использовании связанной архитектуры каждый раз, когда адрес обновляется, вы должны отзывать кэшированные данные. Таким образом, при каждом обновлении служба адреса должна связываться со службой client для отзыва кеша. Вам нужно будет обновить не только новую службу, но и саму службу адреса .

В архитектуре EDA / MDA вам нужна только служба адреса, чтобы сообщить о том, что произошло изменение. Затем все заинтересованные стороны получат сообщение и отзовут свои кэшированные данные.

Важные понятия:

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

Преимущества:

  • Слабая связь. Ни одна из служб не знает друг о друге в отношении обновления данных.
  • Долговечность - гарантирует, что сообщение будет доставлено, даже если служба поддержки клиентов не работает. Всякий раз, когда потребитель снова встает, все сообщения будут там.
  • Масштабируемость. Поскольку сообщения хранятся в корзине, нет необходимости ждать ответов. Мы создаем асинхронную связь между всеми сервисами.
  • Гибкость. Отправитель сообщения не знает, кто его получит. Это означает, что вы можете легко добавить новых потребителей (новую функциональность) с меньшими затратами.

Недостатки:

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

Обмен сообщениями может быть сложным, но в то же время мощным.

# Что такое Кафка?

Kafka - это система публикации / подписки с открытым исходным кодом, впервые разработанная LinkedIn и открытая в 2011 году. Также известна как распределенная система событий.

Сообщения сохраняются на диске в течение определенного периода, известного политикой хранения.

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

  • ETL (извлечение, преобразование, загрузка)
  • CDC (сбор измененных данных)
  • BDI (захват больших данных)

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

Каждый брокер отвечает за получение сообщений от производителей и передачу этих сообщений на диск. Брокер также отвечает за ответы на запросы потребителей и их обслуживание.

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

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

Kafka - это центральный узел для всех событий в системе.

# Практический пример

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

У нас будет две службы: потребитель и производитель.

Производитель будет нести ответственность за получение HTTP-запросов. В каждом запросе мы генерируем несколько обновлений данных. Эти обновления данных должны распространяться через службы, которые кэшируют такие данные. Через систему сообщений все заинтересованные стороны получат уведомление через тематическое сообщение.

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

Требования:

  • Spring boot → Чтобы у нас был рабочий и настраиваемый пример.
  • Docker → Таким образом, вы можете запускать все в любой среде.
  • Apache Kafka → Сервер сообщений.
  1. Установите docker-compose по следующей ссылке.

2. Откройте Spring Initializer и создайте проект Spring со следующими свойствами, а затем нажмите Создать.

3. Повторите шаг 1, но для потребителя.

4. Создайте папку с извлеченными обоими загруженными zip-файлами.

5. Создайте файл с именем docker-compose.yml и добавьте содержимое ниже. Тем самым мы определяем наш кластер Kafka, который будет подключаться к нашему приложению.

  • Версия → Версия Docker.
  • Службы → Все службы в одной docker-compose могут видеть друг друга. В целях связи вы можете использовать имя службы, так как докер определит соответствующее местоположение.

Примечание. Отключив автоматическое создание тем, мы указываем, что будем создавать свои собственные.

6. Чтобы запустить обе службы, вам нужно всего лишь выполнить приведенную ниже команду docker.

Должен быть доступен следующий контейнер:

7. Пора кодировать нашу бизнес-логику. Для каждого микросервиса у нас будет структура «два пакета».

  • Конфиг → Конфигурация производителя / потребителя.
  • Контроллер → Контроллеры REST или сообщений.

8. Начнем с настройки нашего производителя. В его файле зависимостей вставьте конфигурацию ниже.

Примечание. Lombok - это зависимость, которая позволяет нам удалить часть шаблона, созданного конструкторами, сеттерами и геттерами.

9. Давайте добавим в файл конфигурации приложения указанные ниже свойства.

10. Мы на два шага ближе к завершению настройки производителя. Создайте класс чтения свойств.

Примечание: аннотация Lombok @Data сгенерирует во время сборки соответствующий конструктор, геттеры и сеттеры. .

11. Наконец, что не менее важно, представьте компоненты конфигурации нашего производителя.

  • Мы начинаем с введения конфигураций наших производителей через карту. В этом примере мы добавляем стандартные. Для ключа мы будем использовать сериализатор String Kafka, а для значения - JSON.
  • Определите фабрику производителя. В основном из-за того, что мы настраиваем конфигурацию нашего производителя.
  • Мы будем использовать шаблон Kafka для отправки сообщений на сервер Kafka. У нас есть значение объекта, поскольку в конечном итоге мы хотим поддерживать несколько типов объектов.
  • Вводя новую тему, мы говорим Кафке создать ее.

12. С нашим набором конфигурации нам нужно только определить объект, который будет перемещаться по сообщениям и соответствующий контроллер.

Каждый раз, когда вызывается конечная точка HTTP production, создаются сообщения x, которые отправляются на сервер Kafka с объектами, которые мы хотим удалить из кеша.

Вы должны увидеть следующий результат всякий раз, когда вызываете http: // localhost: 8002 / produc.

13. Определив нашего производителя, определите потребителя. Шаги аналогичны шагам выше. Задайте для application.yml конфигурацию, указанную ниже.

Примечание. Зависимости Gradle такие же.

14. Добавьте следующий класс конфигурации:

  • То же объяснение, что и выше для компонента New Topic.
  • Мы определяем наши потребительские десериализаторы.
  • Мы устанавливаем заводское определение.

15. Добавьте те же сущности PropertiesReader и CachedEntity в свою кодовую базу.

16. Добавьте следующий контроллер сообщений.

  • Мы определяем потребительский метод, аннотированный аннотацией KafkaListener. Это позволит вам изучить конкретную тему.

В настоящее время мы просто регистрируем полученную полезную нагрузку.

После запуска потребительского приложения вы должны увидеть следующий результат:

После всех этих шагов мы встраиваем MDA в нашу архитектуру микросервисов. Поздравляю!

# Заключение

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

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

Не стесняйтесь делиться в комментариях, насколько полезной была эта статья для вас!

# Полезные ресурсы