Способы обмена DTO между микросервисами?

33

Мой сценарий таков.

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

Я стараюсь сделать все сервисы максимально независимыми, но у меня возникли некоторые проблемы. Команда определилась с DTO, которое мы хотели бы использовать. Внешние службы (получатели данных датчиков) будут получать данные своим уникальным способом, затем преобразовывать их в объект JSON (DTO) и отправлять их в брокер сообщений. Потребители сообщений будут точно знать, как читать сообщения с данными датчика.

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

Я собираюсь неправильно спроектировать систему? Если нет, то каким образом можно обойти это или хотя бы ослабить мои заботы?

nbaughman
источник
Какими DTO вы делитесь и какой протокол используете между сервисами? Можно, например, поделиться protoфайлом для gRPC или avroсхемой для Kafka и сгенерировать DTO в обоих сервисах, но я не буду делить общую библиотеку между двумя проектами.
Винсент Савард
Кодированные строки JSON и AMQP. Я бы предпочел не использовать ничего конкретного языка.
nbaughman

Ответы:

38

Мой совет? Не разделяйте эти DTO между приложениями в какой-либо библиотеке. Или, по крайней мере, не делай этого прямо сейчас.

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

Служба, которая отправляет DTO, должна быть жесткой в ​​своем контракте сообщений, как Rest API. Служба не может изменить DTO таким образом, чтобы это могло нарушить работу других служб, которые уже потребляют информацию из DTO.

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

Но если эта ситуация действительно беспокоит вас, вы можете следовать правилу трех :

Есть два «правила трех» для повторного использования: (а) в три раза сложнее создать повторно используемые компоненты, чем одноразовые компоненты, и (б) повторно используемый компонент должен быть опробован в трех различных приложениях, прежде чем он станет достаточно общим принять в библиотеку повторного использования.

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

Dherik
источник
1
Очень ценится. Это действительно одна из немногих серьезных проблем, с которыми я сталкиваюсь. Не достаточно, чтобы держать меня ночью, но достаточно, чтобы беспокоить меня.
nbaughman
4
Дублированные DTO (в разных и очень независимых сервисах) не нарушают DRY. Вот и все.
августа
3
По-видимому, нет причин не копировать исходный код DTO непосредственно из одного проекта в другой, как разовую операцию, хотя тогда все части, не требующиеся в новом проекте, вероятно, следует удалить.
BDSL
1
Даже целая служба может быть удалена, не вызывая серьезных проблем для всей системы. Идеально.
Laiv
4
Чтобы прояснить суть ответа, при разработке микросервисов каждый сервис должен разрабатываться так, как если бы он не знал о других сервисах, за исключением фактических контрактов, которые могут ему потребоваться.
Джонатан ван де Вин
12

Когда дело доходит до микросервисов, жизненные циклы разработки сервисов тоже должны быть независимыми. *

Разные SLDC и разные команды разработчиков

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

Разные потребности, разные технологии

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

DTO не являются ни бизнес-правилами, ни контрактами на обслуживание

Что такое DTO? Простые объекты без какой-либо другой цели, кроме перемещения данных с одной стороны на другую. Сумки добытчиков и сеттеров. Это не тот вид «знания», который стоит использовать повторно, потому что знаний вообще нет. Их волатильность также делает их плохими кандидатами на связывание.

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

Разное дело, разные интерпретации

Хотя между сервисами могут быть (и будут) сквозные концепции, это не означает, что нам нужно навязывать каноническую модель, чтобы заставить все сервисы интерпретировать их одинаково.

Тематическое исследование

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

Служба поддержки клиентов, благодаря своему доменному языку , реализует услуги, основанные на концепции клиентов, где клиенты - это лица . Например, клиенты моделируются как имя , фамилия , возраст , пол , адрес электронной почты , телефон и т. Д.

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

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

Ссылки по теме


* Вот в чем сильные стороны этой архитектуры

LAIV
источник
Спасибо! Практические примеры - это то, что помогло мне определить, следует ли разделять DTO или нет. Теперь я уверен, почему я не хотел делиться ими.
Игорь
8

Я стараюсь сделать все сервисы максимально независимыми

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

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

Кроме того, вы хотите, чтобы ваши события представляли связанные с бизнесом события, а не технические события. Например, предпочитаю OrderCancelledсобытие OrderUpdatedс status: "CANCELLED".

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

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

В вашем случае, однако, как ваши публикуют данные датчика, это может иметь смысл иметь службы, слушать события и публиковать новый поток «бизнес - события», например TemperatureThresholdExceeded, TemperatureStabilised.

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

Лучше иметь слишком мало, слишком большие услуги, чем иметь слишком много, слишком маленькие услуги.

Пит
источник
Я определенно согласен. Данные датчика поступают прямо в микросервис, который анализирует сообщение и преобразует его в формат, согласованный для всей организации, прежде чем опубликовать его посреднику. У нас будут некоторые службы, которые читают сообщение и сохраняют его в базе данных, и другие, которые выполняют анализ сообщения и делают с ним свое дело. Каждый сервис по своей природе не имеет большого количества дел, что приводит (надеюсь) к довольно простым услугам.
nbaughman
2
@ Nickdb93 - В вашем случае, когда вы публикуете данные датчиков, может иметь смысл иметь сервис, слушать события и публиковать новый поток «бизнес-событий», например TemperatureThresholdExceeded, TemperatureStabilised. (добавлено в ответ)
Пит