Come condividere DTO tra microservizi

1. Panoramica

I microservizi sono diventati popolari negli ultimi anni. Una delle caratteristiche essenziali dei microservizi è che sono modulari, isolati e facili da scalare. I microservizi devono collaborare e scambiare dati. Per ottenere ciò, creiamo oggetti di trasferimento dati condivisi chiamati DTO.

In questo articolo presenteremo i modi in cui i DTO vengono condivisi tra i microservizi.

2. Esposizione di oggetti di dominio come DTO

I modelli che rappresentano il dominio dell'applicazione vengono gestiti tramite microservizi. I modelli di dominio sono problemi diversi e li separiamo dai modelli di dati nel livello DAO.

La ragione principale di ciò è che non vogliamo esporre ai clienti la complessità del nostro dominio attraverso i servizi. Invece, esponiamo i DTO tra i nostri servizi che servono i client delle applicazioni tramite le API REST. Mentre i DTO passano tra questi servizi, li convertiamo in oggetti di dominio .

L'architettura orientata ai servizi sopra mostra schematicamente i componenti e il flusso di DTO agli oggetti di dominio.

3. Condivisione DTO tra microservizi

Prendiamo, ad esempio, il processo di un cliente che ordina un prodotto. Questo processo si basa sul modello Customer-Order . Diamo un'occhiata al processo dal lato dell'architettura del servizio.

Supponiamo che il servizio clienti invii i dati della richiesta al servizio ordini come:

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

I servizi Cliente e Ordine comunicano tra loro tramite contratti . Il contratto, che altrimenti è una richiesta di servizio, viene visualizzato in formato JSON. Come modello Java, la classe OrderDTO rappresenta un contratto tra il servizio clienti e il servizio ordini:

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

3.1. Condivisione di DTO mediante moduli client (librerie)

Un microservizio richiede determinate informazioni da altri servizi per elaborare qualsiasi richiesta. Supponiamo che esista un terzo microservizio che riceve le richieste di pagamento degli ordini. A differenza del servizio Ordini, questo servizio richiede diverse informazioni sul cliente:

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

Se aggiungiamo anche un servizio di consegna, le informazioni sui clienti avrebbero:

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

Quindi, l'inserimento della classe CustomerDTO in un modulo condiviso non serve più allo scopo previsto. Per risolvere questo problema, ci avviciniamo a un metodo diverso.

All'interno di ogni modulo di microservizio, creiamo un modulo client (libreria) e accanto ad esso un modulo server :

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

Il modulo order-client contiene un DTO condiviso con il servizio clienti. Pertanto, il modulo order-client ha la seguente struttura:

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

L'OrderClient è un'interfaccia che definisce un ordine metodo di elaborazione di richieste di ordine:

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

Per implementare il metodo order , utilizziamo l' oggetto RestTemplate per inviare una richiesta POST al servizio Order:

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

Inoltre, il modulo order-client è pronto per l'uso. Ora diventa una libreria dipendente del modulo del servizio clienti :

[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

Ovviamente, questo non ha scopo senza il modulo order-server di esporre l'endpoint del servizio "/ create" al client dell'ordine:

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

Grazie a questo endpoint di servizio, il servizio clienti può inviare una richiesta d'ordine tramite il proprio client di ordinazione. Utilizzando il modulo client, i microservizi comunicano tra loro in modo più isolato. Gli attributi nel DTO vengono aggiornati all'interno del modulo client. Pertanto, l'interruzione del contratto è limitata ai servizi che utilizzano lo stesso modulo client.

4. Conclusione

In questo articolo, abbiamo spiegato un modo per condividere oggetti DTO tra microservizi. Nella migliore delle ipotesi, otteniamo questo risultato stipulando contratti speciali come parti di moduli client di microservizi (librerie). In questo modo, separiamo il client del servizio dalla parte server che contiene la risorsa API. Di conseguenza, ci sono alcuni vantaggi :

  • Non c'è ridondanza nel codice DTO tra i servizi
  • L'interruzione del contratto è limitata ai servizi che utilizzano la stessa libreria client

Un esempio di codice di un'applicazione Spring Boot è disponibile su GitHub.