Approfondimenti28/6/2024

Le architetture a microservizi e i monoliti modulari

agile software development
application modernization
cloud native

Articolo a cura di

Stefano Bruna

Chief Technology Officer

Linkedin

Negli ultimi anni, l’adozione delle architetture basate su microservizi ha rivoluzionato il panorama dello sviluppo software. Questo paradigma offre una robusta soluzione alle sfide poste dalle moderne applicazioni, in particolare per quanto riguarda la scalabilità e la gestione del debito tecnico. Tuttavia, come ogni scelta tecnologica, presenta vantaggi e complessità che devono essere attentamente valutati.

I vantaggi delle architetture a microservizi

Uno dei principali punti di forza dei microservizi è la capacità di scalare in modo indipendente i singoli componenti dell’applicazione. Questo permette di ottimizzare l’uso delle risorse e di mantenere alte prestazioni anche in presenza di un elevato carico di lavoro. La scalabilità funzionale è un altro aspetto cruciale: i microservizi consentono di aggiungere o modificare funzionalità senza impattare negativamente sul sistema nel suo complesso.  

La modularità dei microservizi facilita lo sviluppo indipendente, permettendo ai team di lavorare in parallelo su diverse funzionalità senza interferenze reciproche. Questo approccio favorisce una rapida evoluzione tecnologica, poiché ogni microservizio può adottare lo stack tecnologico più adatto al suo specifico dominio applicativo.  

Inoltre, le architetture a microservizi sono intrinsecamente “cloud ready”, integrandosi facilmente con i prodotti Platform as a Service (PaaS) offerti dal cloud. Questo disaccoppiamento tra i componenti permette di pubblicare funzionalità tramite interfacce “business oriented”, nascondendo i dettagli tecnici e rendendo i servizi facilmente riutilizzabili in diversi contesti applicativi.

Le sfide delle architetture distribuite

Nonostante i numerosi vantaggi, le architetture a microservizi non sono prive di sfide. La suddivisione della complessità in domini funzionali più piccoli (complessità funzionale interna) rende ogni singolo componente più gestibile, ma aumenta la complessità tecnologica complessiva della soluzione (complessità tecnologica esterna).  

La comunicazione e la collaborazione tra microservizi, che avviene tramite protocolli di rete, introduce ulteriori sfide, soprattutto in termini di gestione delle condizioni di errore e implementazione di pattern come Retry e Circuit Breaker.  

L’ambiente di esecuzione di una soluzione a microservizi è generalmente molto più complesso rispetto a quello di un’architettura monolitica. La necessità di automatizzare i processi di build e deploy, dotarsi di strumenti di monitoring e observability, e gestire un numero elevato di processi in esecuzione richiede un approccio DevOps rigoroso e strumenti avanzati di containerizzazione e orchestrazione.

Bounded contexts e transazioni distribuite

In questo contesto, la suddivisione del dominio applicativo in bounded contexts specifici introduce ulteriori complessità, soprattutto per quanto riguarda la gestione delle transazioni distribuite. I bounded contexts rappresentano aree di responsabilità chiaramente definite all'interno di un sistema, con ciascun microservizio incaricato di implementare funzionalità ben precise. Tuttavia, la complessità emerge quando i processi funzionali attraversano più bounded contexts, rendendo necessaria una gestione oculata delle interazioni tra i microservizi.  

Una comunicazione eccessiva tra i microservizi può portare a problemi di performance, congestioni di rete e riduzione delle prestazioni complessive del sistema. Per evitare questi problemi, è essenziale progettare i microservizi e le loro interfacce in modo che le dipendenze tra di essi siano ridotte al minimo.  

L’adozione di pattern come SAGA, che suddividono una transazione complessa in passi più piccoli gestiti da microservizi specifici, rappresenta una soluzione robusta. Il termine “SAGA“ non è un acronimo, ma è ispirato al concetto di una storia o racconto che descrive come eseguire una sequenza di operazioni atomiche. Il pattern SAGA, infatti, suddivide una transazione complessa in passi più piccoli, ognuno dei quali è gestito da un microservizio specifico. Ogni passo della transazione è rappresentato da una "saga" composta da operazioni di conferma (commit) e operazioni di annullamento (rollback). Se un passo della transazione fallisce, la "saga" può essere eseguita all'indietro, annullando le operazioni precedenti tramite le operazioni di annullamento corrispondenti.  

Questo approccio permette di gestire le transazioni distribuite in modo più robusto ed efficiente rispetto alle tradizionali transazioni globali.

Monoliti modulari: una soluzione intermedia

Una possibile evoluzione del paradigma dei microservizi è rappresentata dai monoliti modulari. Questa architettura cerca di mantenere i vantaggi dei microservizi, come la modularità e il disaccoppiamento, riducendo al contempo la complessità tecnologica. I monoliti modulari permettono di evitare le transazioni distribuite accorpando i bounded contexts coinvolti, delegando la gestione delle transazioni alla base di dati.  

Framework come Spring Modulith stanno emergendo per facilitare l’implementazione di questa architettura, supportando la verifica dei moduli, i test di integrazione e l’osservazione del comportamento dell’applicazione a livello di modulo.

Verso una soluzione ibrida

L’approccio ibrido, che combina elementi di architetture monolitiche e distribuite, potrebbe rappresentare una soluzione intermedia efficace per molte applicazioni moderne. Una grande applicazione potrebbe essere costituita sia da monoliti modulari che da microservizi, riducendo la complessità delle transazioni distribuite e preservando al contempo i benefici della modularità. 

Ciò non mette in discussione le architetture a microservizi, o le architetture monolitiche. Le architetture monolitiche possono ancora oggi essere vantaggiose in certi contesti, e anche i microservizi continueranno ad esserlo per molti altri. 

Non esiste una soluzione unica che si adatti a tutti i contesti applicativi. È essenziale valutare attentamente le esigenze specifiche di ciascun progetto e considerare le diverse opzioni architetturali disponibili. La vera sfida risiede nel discernere quando e quale paradigma applicare, per garantire il successo e la sostenibilità delle soluzioni software nel lungo periodo. 

👉Qui le testate che hanno ripreso l'articolo integrale: 

01net.it: https://lnkd.in/gkbqaND8 
Il Corriere della Sicurezza: https://lnkd.in/gQRTFyt4 
Tech Business: https://lnkd.in/gtGaRBYe