Где и когда запрашивать ФИО пользователей в микросервисной архитектуре: при создании, хранении или извлечении сообщений?

У меня микросервисная архитектура, в которой реализована система обмена сообщениями. Устроено всё следующим образом:

  • IdentityService — отдельный микросервис, где хранятся ФИО (имена) пользователей.
  • MailboxService — сервис, который управляет почтовыми ящиками и сообщениями. Здесь хранятся сообщения, айдишники отправителя и получателя, а также email-адреса (email — часть Mailbox).
  • GatewayService — API-слой, выступает оркестратором между сервисами.

Каждое сообщение содержит senderId и recipientId, а также имена этих пользователей (senderName, recipientName). Проблема в том, что имена живут только в IdentityService, а сообщения создаются и хранятся в MailboxService.

Я не могу понять, где правильнее подставлять ФИО и какие есть архитектурные компромиссы. Понимаю, что это типичная боль микросервисов, а потому мне интересно мнение сообщества. Вот варианты, которые я рассматриваю:

Вариант 1: Получать имена во время создания сообщения в GatewayService

GatewayService не создает письмо, но обращается к MailboxService. В этот момент он запрашивает имена из IdentityService и передаёт их в MailboxService вместе с остальными данными. MailboxService сохраняет senderName, recipientName прямо в Message.

Плюсы:

  • MailboxService ничего не знает про IdentityService.
  • Данные в сообщении самодостаточны, клиенту ничего дополнительно не нужно подгружать.

Минусы:

  • Дублирование данных (имена хранятся и в Identity, и в каждом сообщении).
  • При смене имени у пользователя старые сообщения сохраняют старое имя.
  • GatewayService становится “толстым”, тянет логику из двух сервисов.

Вариант 2: Сохранять имя владельца внутри Mailbox

Когда создаётся почтовый ящик, в него вместе с ID пользователя сохраняется его ФИО. При создании сообщений имя отправителя берётся из Mailbox, а имя получателя — через внешний вызов или тоже из кэша.

Плюсы:

  • Централизация: Mailbox знает всё про своего владельца.
  • MailboxService может самостоятельно создавать сообщения без помощи GatewayService.

Минусы:

  • Повтор данных и потенциальное устаревание при изменении ФИО.
  • MailboxService начинает хранить то, что по смыслу принадлежит Identity — нарушение SRP.

Вариант 3: Не хранить имена вообще, подставлять при извлечении сообщений

MailboxService хранит только ID отправителя и получателя. Когда сообщения извлекаются через GatewayService, он собирает пачку ID и делает запрос в IdentityService, чтобы подставить ФИО.

Плюсы:

  • Чистая архитектура: каждый сервис знает только то, что должен.
  • Имена всегда актуальны.

Минусы:

  • Усложнение логики извлечения (нужно делать join-like запрос).
  • Производительность — при большом числе сообщений и пользователей запросы к Identity могут стать узким местом. Благо она не предполагает высокой нагрузки (закрытая сеть, слабый трафик и юзеров всего пару тысяч)

Вопрос:

Какой из этих подходов является более корректным и принятым в микросервисной архитектуре, когда речь идёт об использовании “вторичных” данных другого сервиса (вроде ФИО), которые не участвуют в бизнес-логике, а нужны только для отображения?


Ответы (1 шт):

Автор решения: NirR0X

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

→ Ссылка