Учитывая, что у меня есть два микросервиса: Service A и Service B.
Службе А принадлежат полные данные о клиентах, а службе Б требуется небольшое подмножество этих данных (которое она получает от службы А, скажем, через какую-то массовую загрузку).
Оба сервиса хранят клиентов в собственной базе данных.
Если службе B затем необходимо взаимодействовать со службой A, скажем, для получения дополнительных данных (например, GET /customers/{id}), ей явно нужен уникальный идентификатор, который используется двумя службами.
Поскольку идентификаторы являются идентификаторами GUID, я мог бы просто использовать PK из службы A при создании записи в службе B. Таким образом, оба PK совпадают.
Однако это звучит очень хрупко. Один из вариантов — сохранить «внешний идентификатор» (или «исходный идентификатор») в виде отдельного поля в службе B и использовать его для взаимодействия со службой A. И, вероятно, это строка, поскольку однажды она может не быть GUID.
Есть ли «лучшая практика» в этом отношении?
обновлять
Поэтому я провел еще несколько исследований и нашел несколько связанных обсуждений:
Следует ли раскрывать первичный ключ в URL-адресах REST API?
Является ли плохой практикой предоставлять идентификатор базы данных клиенту в вашем REST API?
заключение
Я думаю, что моя идея попытаться сохранить оба первичных ключа для клиента одинаковыми в службах A и B была просто неправильной. Это потому что:
Итак, теперь я думаю, что любая служба может предоставлять данные о клиенте через свой собственный уникальный идентификатор (в моем случае GUID PK), и если одной службе необходимо получить дополнительные данные о клиенте из другой службы, она должна хранить другой идентификатор/ключ службы и использовать это. Итак, по сути, вернемся к моей идее «внешнего идентификатора» или «идентификатора источника», но, возможно, более конкретно, как «идентификатор службы B».
Да, мне, конечно, нужен внешний идентификатор, но мой вопрос заключался в том, использовать ли их в качестве первичных ключей базы данных в обеих службах. Мое предложение - нет, потому что это зависит от: а) PK в любой из служб не меняется (что не всегда может быть гарантировано) и б) уникальный идентификатор для клиента может быть, скажем, адресом электронной почты и, следовательно, не может использоваться в качестве База данных ПК. Так что я действительно ответил на свой вопрос здесь. Я действительно просто надеялся на блог или статью где-нибудь, которая просто подтвердит это.
Что ж, я думаю, это классный подход, которому мы можем следовать.
Зачем вам это нужно в первую очередь? Если это клиент, у него, вероятно, есть идентификатор клиента, который компания использует внутри компании (например, для выставления счета или внутренней ссылки на клиента). Это ваше уникальное значение, которое вы также используете для вызова другой службы. GUID, автоинкремент и т. д. "первичный" ключ - это просто инструмент RDBM для моделирования отношений, который может отсутствовать в БД на основе документов. Представьте себе объект заказа и позиции заказа, для СУБД вам нужен столбец автоинкремента для моделирования отношений (т.е. присвоения позиции заказу).
Позиция также может иметь номер позиции, который обычно увеличивается и начинается с 1 для каждого нового заказа, но это не подходит для отношения FK. Теперь, когда у вас есть база данных документов, FK вообще не нужен, поскольку связь определяется структурой документа, то есть { "orderNumber": "O12345", "address": ..., "positions": [{ "positionNumber":1, "description": "Some Product", "priceNet": 10.00, ...]
.
Через rest API вы обычно указываете порядок как /orders/{orderNum}
, а позиции как /orders/{orderNum}/positions
и конкретную позицию: /orders/{orderNum}/positions/({positionNum}
, поэтому нет необходимости раскрывать первичный ключ. P.S. однако лучше решать ваши проблемы с шиной сообщений, каждый раз, когда сущность в службе A изменяется, она запускает событие изменения в шину сообщений, служба B (и другие службы) выбирает свою копию события и обновляет сущность, поэтому ваш услуги не зависимы.
Наличие нескольких служб, синхронно вызывающих друг друга, не является микрослужбой. Это по-прежнему монолитное приложение, разделенное на несколько приложений. Одна служба становится недоступной, и все приложение перестает работать. Это противоположность духу микросервисов.
Я думаю, это немного зависит от источника данных и вашего дизайна. Но одна вещь, которую я бы не стал раскрывать, — это первичный ключ, который представляет собой GUID или целое число с автоинкрементом для внешней службы. Это внутренние детали вашего сервиса, а не то, от чего должны зависеть другие сервисы.
Я бы предпочел иметь внешний идентификатор, который более понятен другим службам и, возможно, бизнесу в целом. Это может быть уникальный номер клиента, номер заказа или номер полиса, а не id
. Вы также можете рассматривать их как «идентификатор компании». Следует также иметь в виду, что внешний идентификатор также может быть доступен конечному пользователю. Следовательно, это повсеместный способ идентификации этой «сущности» во всей организации и службах, независимо от того, используете ли вы Event-Driven-Design или ваши службы взаимодействуют через API. Я бы предоставил только идентификаторы БД инфраструктуре или репозиторию. Кроме того, это всего лишь бизнес/внешний идентификатор.
Что ж, если у вас есть представление о Value Object, бизнес-идентификатор будет намного лучше для разработки.
DDD фокусируется на бизнесе, чистый идентификатор UUID/автоинкремента не может его представить.
Используйте идентификатор бизнес-значения (идентификатор UL), например идентификатор клиента, вместо простого идентификатора.
Он не хрупкий, но необходимый. Даже если вы используете внешний идентификатор, не будет ли это значение по-прежнему храниться в службе A, чтобы соответствовать запросу от службы B?