Обмен данными между микросервисами

Текущая архитектура:

введите описание изображения здесь

Проблема:

У нас есть двухступенчатый поток между интерфейсом и backend-слоями.

  • Первый шаг: Интерфейс проверяет ввод I1 пользователя на микросервисе 1 (MS1)
  • Второй шаг: Интерфейс представляет I1 и дополнительную информацию для микросервиса 2

Микросервис 2 (MS2) должен проверять целостность I1, поскольку он поступает из интерфейса. Как избежать нового запроса к MS1? Какой лучший подход?

Потоки, которые я пытаюсь оптимизировать для удаления шагов 1.3 и 2.3

Поток 1:

  • 1.1 Пользователь X запрашивает данные (MS2_Data) из MS2
  • 1.2 Пользователь X сохраняет данные (MS2_Data + MS1_Data) в MS1
  • 1.3 MS1 проверяет целостность MS2_Data, используя HTTP-запрос B2B.
  • 1.4 MS1 использует MS2_Data и MS1_Data для сохранения и базы данных 1 и создает ответ HTTP.

Поток 2:

  • 2.1 Пользователь X уже имеет данные (MS2_Data), хранящиеся в локальном/сеансовом хранилище
  • 2.2 Пользователь X сохраняет данные (MS2_Data + MS1_Data) в MS1
  • 2.3 MS1 проверяет целостность MS2_Data, используя запрос HTTP B2B
  • 2.4 MS1 использует MS2_Data и MS1_Data для сохранения и базы данных 1 и построения ответа HTTP.

Подход

Одним из возможных подходов является использование HTTP-запроса B2B между MS2 и MS1, но мы будем дублировать проверку на первом этапе. Другим подходом будет дублирование данных от MS1 до MS2. однако это является непомерным из-за объема данных и его волатильности. Дублирование не представляется жизнеспособным вариантом.

Более подходящим решением является мое мнение, что внешний интерфейс должен будет взять всю информацию, требуемую микросервисом 1 на микросервере 2, и доставить его на микросервис 2. Это позволит избежать всех этих запросов HTTP в Интернете.

Проблема заключается в том, как микросервис 1 может доверять информации, отправленной интерфейсом. Возможно, используя JWT, чтобы как-то подписать данные из микросервера 1, и микросервис 2 сможет проверить сообщение.

Примечание Каждый раз, когда микросервис 2 нуждается в информации от микросервиса 1, выполняется запрос HTTP в Интернете. (HTTP-запрос использует ETAG и Cache Control: max-age). Как этого избежать?

Цель архитектуры

введите описание изображения здесь

Микросервис 1 нуждается в данных из микросервиса 2 по требованию, чтобы иметь возможность сохранять MS1_Data и MS2_Data в базе данных MS1, поэтому подход ASYNC с использованием брокера здесь не применяется.

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

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

MS2_Data - это просто идентификатор SID объекта, такой как SID продукта или SID поставщика, который MS1 должен использовать для поддержания целостности данных.

Возможное решение

введите описание изображения здесь

Идея состоит в том, чтобы использовать шлюз в качестве обработки запроса шлюза api, который будет кэшировать некоторый HTTP-ответ от MS1 и MS2 и использовать их в качестве ответа на MS2 SDK и MS1 SDK. Таким образом, связь между SYNC или ASYNC не выполняется непосредственно между MS1 и MS2, и дублирование данных также исключается.

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

Вдохновение: https://aws.amazon.com/api-gateway/ и https://getkong.org/

Связанные вопросы и документация:

Ответ 1

Отметьте раздел Возможное решение по моему вопросу:

Идея состоит в том, чтобы использовать шлюз в качестве обработки запроса шлюза api, который будет кэшировать некоторый HTTP-ответ от MS1 и MS2 и использовать их в качестве ответа на MS2 SDK и MS1 SDK. Таким образом, связь между SYNC или ASYNC не выполняется непосредственно между MS1 и MS2, и дублирование данных также исключается.

Вдохновение: https://aws.amazon.com/api-gateway/ и https://getkong.org/

Ответ 2

Из вопроса и комментариев я понимаю, что вы пытаетесь перестроить блоки для повышения производительности системы. Как описано в диаграммах, вы предполагаете, что вместо микросервиса1, запрашивающего микросервис2, шлюз будет запрашивать микросервис2, а затем запрашивать микросервис1, предоставляя ему информацию из микросервиса2.

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

Чтобы исправить ситуацию, необходимо повысить производительность критического микросервиса2. Это можно сделать путем профилирования и оптимизации программного обеспечения microservice2 (вертикальное масштабирование) и/или вы можете ввести балансировку нагрузки (горизонтальное масштабирование) и выполнить микросервис2 на нескольких серверах. Шаблон проектирования, который будет использоваться в этом случае, Шаблон балансировки нагрузки.

Ответ 3

Трудно судить о жизнеспособности любого решения, не глядя "внутрь" ящиков:

  • Если единственное, о чем вы заботитесь здесь, это остановка внешнего интерфейса от потенциальной подделки данных, вы можете создать своего рода "подпись" пакета данных, отправленного MS2 во внешний интерфейс, и распространить подпись на MS1 вместе с пакетом. Подпись может быть хешем пакета, связанного с псевдослучайным числом, генерируемым детерминированным способом из семени, совместно используемого микросервисами (поэтому MS1 может воссоздать одно и то же псевдослучайное число, как MS2, без необходимости в дополнительном запросе HTTP B2B, а затем проверить целостность пакета).

  • Первая мысль, которая приходит мне на ум, - проверить, может ли быть изменена собственность на данные. Если MS1 должен часто обращаться к подмножеству данных из MS2, МОЖЕТ быть возможным переместить право собственности на это подмножество с MS2 на MS1.

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

Надеюсь, что это поможет!

Ответ 4

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

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

Если ms2data - это информация о продукте, тогда ms2 должен публиковать событие ProductCreated, содержащее ms2data, для шины. Ms1 должен быть подписан на это событие и хранить ms2data в своей собственной базе данных. Теперь, в любое время ms1 требуется ms2data, он будет просто читать его локально, без необходимости выполнять запросы к ms2. Это то, что означает временная развязка. Когда вы следуете этому шаблону, ваше решение становится более отказоустойчивым и выключение ms2 никак не повлияет на ms1.

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

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