How to Share DTO Across Microservices – 如何在微服务间共享DTO

最后修改: 2020年 6月 27日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Microservices have become popular in recent years. One of the essential characteristics of microservices is that they are modular, isolated, and easy to scale. The microservices need to work together and exchange data. To achieve this, we create shared data transfer objects called DTOs.

近几年来,微服务已经变得很流行。微服务的基本特征之一是它们是模块化的、孤立的,并且易于扩展。微服务需要协同工作并交换数据。为了实现这一点,我们创建了共享的数据传输对象,称为DTO。

In this article, we will present ways in which DTOs are shared between microservices.

在这篇文章中,我们将介绍微服务之间共享DTO的方式。

2. Exposing Domain Objects as DTO

2.将域对象作为DTO公开

Models that represent the application domain are managed using microservices. Domain models are different concerns, and we separate them from data models in the DAO layer.

代表应用领域的模型使用微服务进行管理。领域模型是不同的关注点,我们在DAO层将它们与数据模型分开。

The main reason for this is that we don’t want to expose the complexity of our domain through the services to the clients. Instead, we expose DTOs between our services that serve application clients through REST APIs. While DTOs pass between these services, we convert them to domain objects.

其主要原因是,我们不想通过服务将我们的领域的复杂性暴露给客户。相反,我们在通过REST API为应用客户提供服务的服务之间暴露了DTOs。当DTO在这些服务之间传递时,我们将它们转换为域对象

The service-oriented architecture above schematically shows the components and flow of DTO to Domain objects.

上面的面向服务的架构示意性地显示了DTO到域对象的组件和流程。

3. DTO Sharing Between Microservices

3.微服务之间的DTO共享

Take, as an example, the process of a customer ordering a product. This process is based on the Customer-Order model. Let’s look at the process from the side of the service architecture.

以客户订购产品的过程为例。这个过程是基于客户-订单模型的。让我们从服务架构的角度来看看这个过程。

Let’s say that the Customer service sends request data to the Order service as:

假设顾客服务向订单服务发送的请求数据为。

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

The Customer and Order services communicate with each other using contracts. The contract, which is otherwise a service request, is displayed in JSON format. As a Java model, the OrderDTO class represents a contract between the Customer service and the Order service:

客户和订单服务使用合同相互通信。合同,也就是服务请求,以JSON格式显示。作为一个 Java 模型,OrderDTO 类代表了 Customer 服务和 Order 服务之间的合同。

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

    // constructor, getters, setters
}

3.1. Sharing DTO Using Client Modules (Libraries)

3.1.使用客户端模块(库)共享DTO

A microservice requires certain information from other services to process any request. Let’s say there is a third microservice that receives order payment requests. Unlike the Order service, this service requires different customer information:

一个微服务需要其他服务的某些信息来处理任何请求。假设有第三个微服务,接收订单付款请求。与订单服务不同,这个服务需要不同的客户信息。

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

    // constructor, getters, setters
}

If we also add a delivery service, customer information would have:

如果我们还增加了送货服务,客户信息将有。

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

    // constructor, getters, setters
}

So, placing the CustomerDTO class in a shared module no longer serves the intended purpose. To solve this, we approach a different method.

因此,将CustomerDTO类放在一个共享模块中不再能达到预期的目的。为了解决这个问题,我们采取了不同的方法。

Within each microservice module, let’s create a client module (library) and next to it a server module:

在每个微服务模块中,让我们创建一个客户端模块(库) 旁边是一个服务器模块

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

The order-client module contains a DTO shared with Customer service. Therefore, the order-client module has the following structure:

order-client模块包含一个与Customer service共享的DTO。因此,order-client模块有以下结构。

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

The OrderClient is an interface that defines an order method for processing order requests:

OrderClient是一个接口,定义了一个order方法,用于处理订单请求。

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

To implement the order method, we use the RestTemplate object to send a POST request to the Order service:

为了实现order方法,我们使用RestTemplate对象向Order服务发送一个POST请求。

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

Besides, the order-client module is ready for use. It now becomes a dependent library of the customer-service module:

此外,order-client模块已经可以使用了。它现在成为customer-service模块的一个依赖库。

[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

Of course, this has no purpose without the order-server module to expose the “/create” service endpoint to the order client:

当然,如果没有order-server模块将”/create “服务端点暴露给订单客户端,这就没有任何意义。

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

Thanks to this service endpoint, the Customer service can send an order request through its order client. By using the client module, microservices communicate with each other in a more isolated way. Attributes in the DTO are updated within the client module. Therefore, contract breaking is limited to services that use the same client module.

由于这个服务端点,客户服务可以通过其订单客户端发送订单请求。通过使用客户端模块,微服务以一种更加隔离的方式相互通信。DTO中的属性在客户端模块中被更新。因此,合同的破坏仅限于使用相同客户端模块的服务。

4. Conclusion

4.总结

In this article, we explained a way to share DTO objects between microservices. At best, we achieve this by making special contracts as parts of microservice client modules (libraries). In this way, we separate the service client from the server part that contains the API resource. As a result, there are some benefits:

在这篇文章中,我们解释了一种在微服务之间共享DTO对象的方法。在最好的情况下,我们通过将特殊合约作为微服务客户端模块(库)的一部分来实现。通过这种方式,我们将服务客户端与包含API资源的服务器部分分开。因此,有一些好处

  • There is no redundancy in the DTO code between services
  • Contract breaking is limited to services that use the same client library

A code sample of a Spring Boot application is available over on GitHub.

在GitHub上有一个Spring Boot应用程序的代码样本