Microservizi e scambio di messaggi in Spring Boot

In questo articolo vedrai come implementare un’architettura a microservizi impiegando RabbitMQ in applicazioni Spring Boot per lo scambio di messaggi.

Architettura a microservizi? RabbitMQ? Non farti spaventare dai nomi, tra poco ti spiegherò di cosa stiamo parlando.

Se sei capitato qui, sarai interessato al concetto di microservizi. Sul web troverai già molti articoli sulla definizione di microservizi e sui vantaggi che questa architettura comporta, per cui in questo articolo ne parlerò solo brevemente.  Quello che invece voglio farti vedere, è un modo pratico per applicare il concetto di microservizi su applicazioni Spring.

 

Concetto di microservizi

Un’applicazione può essere suddivisa nelle sue funzioni in più servizi. Un micro-servizio è quindi una funzione dell’applicazione che garantisce il suo funzionamento indipendentemente dalle altre, portando ad una alta scalabilità. Inoltre, ogni micro-servizio è progettato per eseguire esclusivamente la sua funzione, risultando in un’applicazione di modeste dimensioni e ben strutturata.

 

RabbitMQ

RabbitMQ non è altro che un “broker di messaggi” che implementa il protocollo AMQP. Funziona come un programma intermedio che permette lo scambio di messaggi tra altre applicazioni, preoccupandosi della convalida, della trasformazione e dello smistamento, utilizzando code.

 

Ottenere RabbitMQ

Per utilizzare RabbitMQ occorre scaricare e installare RabbitMQ Server, tramite uno dei modi proposti dal sito, ad esempio Homebrew (Mac) piuttosto che tramite l’immagine Docker.

Per l’esempio di questo articolo ho utilizzato Homebrew per l’istallazione, dopo di che ho ho avviato RabbitMQ Server da terminale. Di seguito i due comandi rispettivamente per l’istallazione e l’avvio:

brew install rabbitmq
rabbitmq-server
 

Utilizzare RabbitMQ in Spring Boot per lo scambio di messaggi in un'architettura a microservizi

Il prossimo passo consiste nel configurare RabbitMQ all’interno di Spring.

L’esempio di questo post consiste nel far comunicare 2 applicazioni Spring Boot, rappresentanti due servizi, attraverso lo scambio di messaggi su server Rabbit.

Non resta che creare i due progetti Spring Boot seguendo la procedura descritta in questo post.

 

Aggiungere le dipendenze

Per utilizzare RabbitMQ in Spring Boot occorre inserire la sua dipendenza all’interno del file pom.xml (progetti Maven) dell’applicazione. Aggiungiamo la dipendenza in entrambi i progetti creati.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
 

Aggiungere una configurazione RabbitMQ

Il passo successivo consiste nell’impostare i parametri di connessione al server RabbitMQ. Aggiungi le proprietà nel file application.yml sfruttando la configurazione di default di Spring.

spring: 
    rabbitmq: 
        username: guest 
        password: guest 
        host: localhost

Segue, la creazione di una classe di configurazione RabbitMQConfig che definisce il Bean rappresentante la coda Rabbit utilizzata per scambiare i messaggi.

Allo stesso tempo, dobbiamo definire la struttura dell’oggetto che vogliamo scambiare come messaggio, ad esempio l’oggetto Ball che rappresenta una palla. Sarà responsabilità del broker Rabbit deserializzare l’oggetto durante l’inserimento e la ricezione del messaggio, come vedremo tra poco.,

public class Ball implements Serializable { 
    private String color;
    private Integer size; 
    
    // getter and setter
}
@Configuration 
public class RabbitMQConfig { 
    
    @Bean 
    public Queue ballQueue() { 
        return new Queue("ball-queue") 
    } 
}
 

Inviare un messaggio

Realizziamo una API per l’invio di un oggetto Ball da un service all’altro, implementandola all’interno di una delle due applicazioni. Chiamando l’API creata, ci aspettiamo di ricevere l’oggetto nell’altra applicazione passando dal server RabbitMQ.

Crea un nuovo controller BallController come di seguito:

@RestController 
@RequestMapping("api/v1/ball") 
public class BallController { 
    @Autowired 
    private Queue ballQueue; 
    
    @Autowired 
    private RabbitTemplate rabbitTemplate;
    
    @PostMapping 
    public ResponseEntity input(@RequestBody Ball body) { 
        rabbitTemplate.convertAndSend(ballQueue.getName(), body); 
        return ResponseEntity.noContent().build(); 
    } 
}
Schermata pannello di controllo server Rabbit
Pannello Queues del server Rabbit
 

Recuperare un messaggio

Dobbiamo ora configurare il secondo service per recuperare e gestire i messaggi.

Per prima cosa dobbiamo impostare una porta diversa all’altro service, al fine di lanciare, al termine, entrambi i servizi. Per far questo, aggiungi alle proprietà la nuova porta, ad esempio 8081, diversa dalla porta di default 8080.

server:
  port: 8081

Crea una classe BallDataConsumer che contiene un metodo receiveMessage. Aggiungeremo questo metodo all’interno della configurazione affinché venga eseguito automaticamente alla presenza di un nuovo messaggio all’interno della coda.

@Component 
public class BallDataConsumer { 
    public void receiveMessage(Ball data) { 
        // Do something 
        System.out.println(String.format("Consuming ball data %s", data.toString())); 
    } 
}

A questo punto dovrai modificare la classe RabbitMQConfig aggiungendo a quella presente (Queue) le nuove configurazioni:

@Configuration 
public class RabbitMQConfig { 
    
    @Bean 
    public Queue ballQueue() { 
        return new Queue("ball-queue") 
    } 
    
    @Bean 
    public MessageListenerAdapter ballMessageAdapter(BallDataConsumer consumer) { 
        return new MessageListenerAdapter(consumer, "receiveMessage"); 
    } 
    @Bean 
    public SimpleMessageListenerContainer ballMessageListenerContainer(ConnectionFactory connectionFactory, BallDataConsumer consumer) { 
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 
        container.setConnectionFactory(connectionFactory); 
        container.setQueueNames(ballQueue().getName()); 
        container.setMessageListener(ballMessageAdapter(consumer)); 
        return container; 
    } 
}
 

A questo punto abbiamo completato tutte le configurazioni e implementazioni necessarie a realizzare uno scambio di messaggi tra applicazioni Spring Boot, impiegando un’architettura a microservizi.

Il risultato dell’architettura è rappresentato dalla figura sottostante.

Figura rappresentante lo scambio di messaggi in una architettura a microservizi
Architettura dell'applicazione

Recommended Posts

No comment yet, add your voice below!


Add a Comment

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *