«1. Обзор

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

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

2. Предоставление объектов домена как DTO

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

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

Вышеприведенная сервис-ориентированная архитектура схематично показывает компоненты и поток DTO для объектов домена.

3. Совместное использование DTO между микросервисами

Возьмем, к примеру, процесс заказа клиентом продукта. Этот процесс основан на модели «клиент-заказ». Давайте посмотрим на процесс со стороны сервисной архитектуры.

Предположим, что служба Customer отправляет данные запроса службе Order следующим образом:

"order": {
    "customerId": 1,
    "itemId": "A152"
}

Службы Customer и Order взаимодействуют друг с другом с помощью контрактов. Контракт, который в противном случае является запросом на обслуживание, отображается в формате JSON. В качестве модели Java класс OrderDTO представляет контракт между службой Customer и службой Order:

public class OrderDTO {
    private int customerId;
    private String itemId;

    // constructor, getters, setters
}

3.1. Совместное использование DTO с использованием клиентских модулей (библиотек)

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

public class CustomerDTO {
    private String firstName;
    private String lastName;
    private String cardNumber;

    // constructor, getters, setters
}

Если мы также добавим службу доставки, информация о клиенте будет иметь:

public class CustomerDTO {
    private String firstName;
    private String lastName;
    private String homeAddress;
    private String contactNumber;

    // constructor, getters, setters
}

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

Внутри каждого микросервисного модуля создадим клиентский модуль (библиотеку), а рядом с ним серверный модуль:

order-service
|__ order-client
|__ order-server

Модуль order-client содержит DTO, совместно используемый службой Customer. Таким образом, модуль order-client имеет следующую структуру:

order-service
└──order-client
     OrderClient.java
     OrderClientImpl.java
     OrderDTO.java

OrderClient — это интерфейс, который определяет метод заказа для обработки запросов заказа:

public interface OrderClient {
    OrderResponse order(OrderDTO orderDTO);
}

Для реализации метода заказа мы используем объект RestTemplate отправить POST-запрос сервису Order:

String serviceUrl = "http://localhost:8002/order-service";
OrderResponse orderResponse = restTemplate.postForObject(serviceUrl + "/create", 
  request, OrderResponse.class);

Кроме того, модуль order-client готов к работе. Теперь он становится зависимой библиотекой модуля обслуживания клиентов:

[INFO] --- maven-dependency-plugin:3.1.2:list (default-cli) @ customer-service ---
[INFO] The following files have been resolved:
[INFO]    com.baeldung.orderservice:order-client:jar:1.0-SNAPSHOT:compile

Конечно, это не имеет смысла без модуля сервера заказов, который предоставляет конечную точку службы «/create» клиенту заказа: ~~ ~

@PostMapping("/create")
public OrderResponse createOrder(@RequestBody OrderDTO request)

Благодаря этой конечной точке службы служба клиентов может отправлять запрос заказа через своего клиента заказа. С помощью клиентского модуля микрослужбы взаимодействуют друг с другом более изолированным образом. Атрибуты в DTO обновляются в клиентском модуле. Таким образом, нарушение контракта ограничивается службами, использующими один и тот же клиентский модуль.

4. Заключение

В этой статье мы объяснили способ совместного использования объектов DTO между микросервисами. В лучшем случае мы достигаем этого, заключая специальные контракты в составе клиентских модулей (библиотек) микросервисов. Таким образом мы отделяем клиент сервиса от серверной части, содержащей ресурс API. В результате есть некоторые преимущества:

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

Пример кода приложения Spring Boot доступен на GitHub. .