Поделиться через


Асинхронное взаимодействие на основе сообщений

Совет

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

Архитектура микрослужб .NET для контейнерных приложений .NET для эскиза обложки.

Асинхронное обмен сообщениями и взаимодействие на основе событий критически важно при распространении изменений в нескольких микрослужбах и связанных с ними моделях домена. Как упоминалось ранее в обсуждении микрослужб и ограниченных контекстов (BC), модели (пользователь, клиент, продукт, учетная запись и т. д.) могут иметь разное значение для разных микрослужб или BC. Это означает, что при внесении изменений необходимо найти способ согласовать эти изменения для разных моделей. Для решения этой проблемы необходимо обеспечить итоговую согласованность и взаимодействие, управляемое событиями, на основе асинхронного обмена сообщениями.

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

Сообщение состоит из заголовка (метаданные, например, идентификатор или данные для обеспечения безопасности) и текста. Обычно сообщения отправляются с использованием асинхронного протокола, например AMQP.

Предпочтительной инфраструктурой для такого типа обмена данными в сообществе микрослужб является упрощенный брокер сообщений, который отличается от больших брокеров и оркестраторов, используемых в SOA. В упрощенном брокере сообщений инфраструктура обычно "глупая", выступающая только в качестве брокера сообщений, с простыми реализациями, такими как RabbitMQ или масштабируемая служебной шиной в облаке, например Служебная шина Azure. При таком сценарии основная обработка данных выполняется в конечных точках, там, где создаются и используются сообщения, т. е. микрослужбами.

Есть еще правило, которого следует придерживаться, насколько это возможно. Между внутренними службами следует использовать только асинхронный обмен сообщениями, а синхронное взаимодействие (например, HTTP) использовать только для клиентских приложений, работающих со службами интерфейса (шлюзами API и микрослужбами первого уровня).

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

Взаимодействие на основе сообщений с одним получателем

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

Взаимодействие на основе сообщений с одним получателем особенно хорошо подходит в случаях отправки асинхронных команд из одной микрослужбы другую. На рис. 4-18 иллюстрируется этот метод.

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

Одна микрослужба, получающая асинхронное сообщение

Рис. 4-18. Одна микрослужба, получающая асинхронное сообщение

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

Взаимодействие на основе сообщений с несколькими получателями

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

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

Асинхронное взаимодействие, управляемое событиями

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

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

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

Важно то, что вы можете передать сообщение сразу нескольким микрослужбам, которые подписаны на это событие. Чтобы сделать это, вы можете использовать систему обмена сообщениями о публикациях и подписках на основе взаимодействия, управляемого событиями, как показано на рис. 4-19. Этот механизм публикаций и подписок используется не только в архитектуре микрослужб. Он похож на способ, которым взаимодействуют ограниченные контексты в DDD, или на способ распространения обновлений от баз данных записи к базам данных чтения в архитектурах типа разделение команд и запросов (CQRS). Цель — получить итоговую согласованность между различными источниками данных в распределенной системе.

Схема, демонстрирующая асинхронное взаимодействие, управляемое событиями.

Рис. 4-19. Асинхронное взаимодействие, управляемое сообщением о событиях

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

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

При использовании шины событий может возникнуть необходимость использования уровня абстракции (например, интерфейса шины событий) на основе соответствующей реализации в классах с кодом, использующим API из брокера сообщений, например RabbitMQ или служебной шины, такой как служебная шина Azure с разделами. Кроме того, может потребоваться использовать шину обслуживания более высокого уровня, например NServiceBus, MassTransit или Brighter , чтобы сформулировать шину событий и опубликовать или подписать систему.

Примечание о технологии обмена сообщениями для производственных систем

Технологии обмена сообщениями, с помощью которых можно реализовать абстрактную шину событий, находятся на разных уровнях. Например, продукты, такие как RabbitMQ (транспорт брокера обмена сообщениями) и Служебная шина Azure сидеть на более низком уровне, чем другие продукты, такие как NServiceBus, MassTransit или Brighter, которые могут работать над RabbitMQ и Служебная шина Azure. Выбор зависит от того, насколько много сложных функций уровня приложения и готовых к использованию возможностей масштабирования необходимо для вашего приложения. Для реализации шины событий, предназначенной только для демонстрации принципа работы и используемой в среде разработки, как было показано на примере eShopOnContainers, будет достаточно простой реализации на основе системы RabbitMQ, работающей в контейнере Docker.

Для построения критически важных и производственных систем, требующих широких возможностей масштабирования, следует использовать служебную шину Azure. Для высокоуровневых абстракций и функций, которые упрощают разработку распределенных приложений, рекомендуется оценить другие коммерческие и открытые служебные автобусы, такие как NServiceBus, MassTransit и Brighter. Кроме того, вы можете создавать свои собственные функции служебной шины на основе низкоуровневых технологий, таких как RabbitMQ и Docker. Однако эта черная работа может оказаться слишком дорогим занятием при разработке корпоративного приложения.

Гибкая публикация в шине событий

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

  • Использование очереди транзакций (на основе DTC), подобной MSMQ. (Этот способ применялся в системах более ранних версий.)

  • Интеллектуальный анализ данных журнала транзакций.

  • Использование полной модели источников событий.

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

Более полное описание проблем в этом пространстве, включая способ публикации сообщений с потенциально неправильными данными, см. в статье "Платформа данных" для критически важных рабочих нагрузок в Azure: каждое сообщение должно обрабатываться.

При использовании асинхронного взаимодействия следует дополнительно рассмотреть вопросы идемпотентности и дедупликации сообщений. Эти вопросы рассматриваются в разделе Реализация взаимодействия между микрослужбами на основе событий (события интеграции) далее в этом руководстве.

Дополнительные ресурсы