微服務之間如何共享DTO?

鍋外的大佬發表於2020-12-22

1. 概述

近些年來,微服務變得越來越流行。微服務基本特徵是模組化、獨立、易於擴充套件的。它們之間需要協同工作並交換資料。為了實現這一點,我們建立了名為 DTO 的共享資料傳輸物件。在本文中,我們將介紹在微服務之間共享DTO的方法。

2. 將域物件釋出為DTO

使用微服務管理表示應用程式域的模型。域模型的關注點與 DTO 不同,我們將它們與DAO層中的資料模型分開。
這樣做的主要原因是我們不想通過服務向客戶暴露我們領域的複雜性。

恰恰相反,我們通過 REST API 暴露 DTO 為客戶端提供服務。當DTO在這些服務之間傳遞時,我們將它們轉換為域物件。

dto

上面的 面向服務架構 示意性地顯示了DTO到域物件的元件和流程。

3. 微服務間共享DTO

以客戶訂購產品的過程為例。此過程基於 Customer-Order 模型,從服務體系結構的角度來看看這個過程。
假設客戶服務將請求資料傳送到訂單服務:

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

CustomerOrder 服務使用 contracts (契約) 進行通訊。contract(或者是服務請求)以JSON格式顯示。作為 Java 模型,OrderDTO 類表示客戶服務和訂單服務之間的契約:

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。因此,order-client模組具有以下結構:

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

OrderClient 是一個介面,它定義了處理訂單請求的order方法:

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

為了實現 order 方法,我們使用 RestTemplate 物件向 order 服務傳送POST請求:

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

此外,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

當然,如果 order-server 模組沒有向 order-client 暴露 /create 服務端點,那也是不行滴!

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

由於這個服務端點,Customer Service 可以通過其order客戶端傳送訂單請求。通過使用客戶端模組,微服務以更加獨立的方式相互通訊。DTO中的屬性在客戶端模組中更新。因此,違背契約僅限於使用相同客戶端模組的服務。

4. 結論

本文解釋了一種在微服務之間共享DTO物件的方法。充其量,我們通過簽訂特殊契約作為微服務客戶端模組(庫)的一部分來實現這一點。通過這種方式,我們將服務客戶端與包含API資源的服務端部分分開。這樣做的好處是:

  • 服務之間沒有冗餘
  • 違反契約僅限於使用同一客戶端的服務
    如果你覺得文章還不錯,記得關注公眾號: 鍋外的大佬
    鍋外的大佬部落格

相關文章