So teilen Sie DTO über Microservices hinweg

1. Übersicht

Microservices sind in den letzten Jahren populär geworden. Eine der wesentlichen Eigenschaften von Mikrodiensten ist, dass sie modular, isoliert und einfach zu skalieren sind. Die Microservices müssen zusammenarbeiten und Daten austauschen. Um dies zu erreichen, erstellen wir gemeinsam genutzte Datenübertragungsobjekte, die als DTOs bezeichnet werden.

In diesem Artikel werden Möglichkeiten vorgestellt, wie DTOs von Microservices gemeinsam genutzt werden.

2. Domänenobjekte als DTO verfügbar machen

Modelle, die die Anwendungsdomäne darstellen, werden mithilfe von Microservices verwaltet. Domänenmodelle sind unterschiedliche Anliegen, und wir trennen sie von Datenmodellen in der DAO-Schicht.

Der Hauptgrund dafür ist, dass wir die Komplexität unserer Domain nicht durch die Services für die Kunden offenlegen möchten. Stattdessen stellen wir DTOs zwischen unseren Diensten bereit, die Anwendungsclients über REST-APIs bedienen. Während DTOs zwischen diesen Diensten übertragen werden, konvertieren wir sie in Domänenobjekte .

Die obige serviceorientierte Architektur zeigt schematisch die Komponenten und den Fluss von DTO zu Domänenobjekten.

3. DTO-Freigabe zwischen Microservices

Nehmen Sie als Beispiel den Prozess eines Kunden, der ein Produkt bestellt. Dieser Prozess basiert auf dem Kundenauftragsmodell . Betrachten wir den Prozess von der Seite der Servicearchitektur.

Angenommen, der Kundendienst sendet Anforderungsdaten an den Bestellservice wie folgt:

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

Der Kunde und der Bestelldienst kommunizieren über Verträge miteinander . Der Vertrag, bei dem es sich ansonsten um eine Serviceanforderung handelt, wird im JSON-Format angezeigt. Als Java-Modell stellt die OrderDTO- Klasse einen Vertrag zwischen dem Kundendienst und dem Bestellservice dar:

public class OrderDTO { private int customerId; private String itemId; // constructor, getters, setters }

3.1. Gemeinsame Nutzung von DTOs mithilfe von Client-Modulen (Bibliotheken)

Ein Microservice benötigt bestimmte Informationen von anderen Diensten, um eine Anfrage zu verarbeiten. Angenommen, es gibt einen dritten Microservice, der Zahlungsanforderungen für Bestellungen empfängt. Im Gegensatz zum Bestellservice erfordert dieser Service unterschiedliche Kundeninformationen:

public class CustomerDTO { private String firstName; private String lastName; private String cardNumber; // constructor, getters, setters }

Wenn wir auch einen Lieferservice hinzufügen, hätten Kundeninformationen:

public class CustomerDTO { private String firstName; private String lastName; private String homeAddress; private String contactNumber; // constructor, getters, setters }

Das Platzieren der CustomerDTO- Klasse in einem gemeinsam genutzten Modul erfüllt also nicht mehr den beabsichtigten Zweck. Um dies zu lösen, nähern wir uns einer anderen Methode.

Erstellen Sie in jedem Microservice-Modul ein Client-Modul (Bibliothek) und daneben ein Server-Modul :

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

Das Order-Client- Modul enthält ein DTO, das für den Kundendienst freigegeben ist. Daher hat das Order-Client- Modul folgende Struktur:

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

Der OrderClient ist eine Schnittstelle, die eine Bestellmethode für die Verarbeitung von Bestellanforderungen definiert :

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

Um die Bestellmethode zu implementieren , verwenden wir das RestTemplate- Objekt, um eine POST-Anforderung an den Bestellservice zu senden:

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

Außerdem ist das Order-Client- Modul einsatzbereit. Es wird nun zu einer abhängigen Bibliothek des Kundendienstmoduls :

[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

Ohne das Order-Server- Modul hat dies natürlich keinen Zweck , den Service-Endpunkt "/ create" dem Order-Client zur Verfügung zu stellen:

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

Dank dieses Service-Endpunkts kann der Kundenservice eine Bestellanforderung über seinen Bestellkunden senden. Durch die Verwendung des Client-Moduls kommunizieren Microservices isolierter miteinander. Attribute im DTO werden im Client-Modul aktualisiert. Daher ist das Brechen von Verträgen auf Dienste beschränkt, die dasselbe Clientmodul verwenden.

4. Fazit

In diesem Artikel haben wir eine Möglichkeit erläutert, DTO-Objekte zwischen Microservices zu teilen. Im besten Fall erreichen wir dies, indem wir spezielle Verträge als Teil von Microservice-Client-Modulen (Bibliotheken) abschließen. Auf diese Weise trennen wir den Service-Client vom Server-Teil, der die API-Ressource enthält. Infolgedessen gibt es einige Vorteile :

  • Es gibt keine Redundanz im DTO-Code zwischen Diensten
  • Vertragsbruch ist auf Dienste beschränkt, die dieselbe Clientbibliothek verwenden

Ein Codebeispiel einer Spring Boot-Anwendung ist auf GitHub verfügbar.