Un'architettura di microservizi è costituita da un insieme di servizi ridotti autonomi. Ogni servizio è indipendente e deve implementare una singola funzionalità aziendale all'interno di un contesto delimitato. Un contesto delimitato è una divisione naturale all'interno di un'azienda e fornisce un limite esplicito all'interno del quale esiste un modello di dominio.
Cosa sono i microservizi?
I microservizi sono ridotti, indipendenti e a regime di controllo libero. Le dimensioni sono tali da consentirne la scrittura e la gestione da parte di un unico piccolo team di sviluppatori.
Ogni servizio è una base di codici distinta, che può essere gestita da un team di sviluppo di piccole dimensioni.
I servizi possono essere distribuiti in modo indipendente. Un team può aggiornare un servizio esistente senza ricompilare e ridistribuire l'intera applicazione.
I servizi sono responsabili della persistenza dei propri dati o dello stato esterno. Questo comportamento differisce dal modello tradizionale, in cui la persistenza dei dati viene gestita da un livello dati distinto.
I servizi comunicano tra loro tramite API ben definite. I dettagli di implementazione interna di ogni servizio sono nascosti da altri servizi.
Supporta la programmazione poliglotta. Ad esempio, i servizi non devono condividere lo stesso stack di tecnologie, librerie o framework.
Oltre ai servizi, in un'architettura di microservizi tipica compaiono alcuni altri componenti:
Gestione/orchestrazione. Questo componente è responsabile del posizionamento dei servizi sui nodi, dell'identificazione degli errori, del ribilanciamento dei servizi tra i nodi e così via. In genere, questo componente è una tecnologia in serie, ad esempio Kubernetes, invece di essere creata in modo personalizzato.
API Gateway. Il gateway API è il punto di ingresso per i client. Invece di chiamare direttamente i servizi, i client chiamano il gateway API, che inoltra la chiamata ai servizi appropriati sul back-end.
I vantaggi associati all'uso di un gateway API includono:
Separa i client dai servizi, di cui può essere effettuato il refactoring o il controllo delle versioni senza la necessità di aggiornare tutti i client.
I servizi possono usare protocolli di messaggistica non compatibili con il Web, come AMQP.
Il gateway API può eseguire altre funzioni trasversali, come l'autenticazione, la registrazione, la terminazione SSL e il bilanciamento del carico.
Criteri predefiniti, ad esempio per la limitazione, la memorizzazione nella cache, la trasformazione o la convalida.
Vantaggi
Agilità. Poiché i microservizi vengono distribuiti in modo indipendente, è più facile gestire le correzioni di bug e i rilasci delle funzionalità. È possibile aggiornare un servizio senza ridistribuire l'intera applicazione ed eseguire il rollback di un aggiornamento in caso di errore. In molte applicazioni tradizionali un bug rilevato in una parte dell'applicazione può bloccare l'intero processo di rilascio. Le nuove funzionalità potrebbero essere bloccate in attesa di una correzione di bug da integrare, testare e pubblicare.
Team dedicati di piccole dimensioni. Un microservizio deve essere sufficientemente piccolo da consentire a un singolo un team responsabile di una funzionalità di crearlo, testarlo e distribuirlo. I team di piccole dimensioni lavorano in modo più flessibile. I team di grandi dimensioni tendono a essere meno produttivi, perché la comunicazione è più lenta, la gestione è più complessa e la flessibilità diminuisce.
Codebase di dimensioni ridotte. In un'applicazione monolitica si verifica una tendenza nel tempo per cui le dipendenze del codice diventano tangente. L'aggiunta di una nuova funzionalità richiede il tocco del codice in molte posizioni. Un'architettura di microservizi non prevede la condivisione di codice o di archivi dati, quindi le dipendenze sono ridotte al minimo ed è più facile aggiungere nuove funzionalità.
Combinazione di tecnologie. I team possono scegliere la tecnologia più adatta al servizio, usando la combinazione di stack tecnologici più appropriata.
Isolamento degli errori. Se un singolo microservizio diventa non disponibile, non interromperà l'intera applicazione, purché i microservizi upstream siano progettati per gestire correttamente gli errori. Ad esempio, è possibile implementare il modello interruttore oppure progettare la soluzione in modo che i microservizi comunichino tra loro usando modelli di messaggistica asincroni.
Scalabilità. È quindi possibile ridimensionare i servizi e aumentare il numero di sottosistemi che richiedono più risorse, senza ampliare il livello di servizio dell'intera applicazione. Usando un agente di orchestrazione, ad esempio Kubernetes, è possibile comprimere una maggiore densità di servizi in un singolo host, che consente un utilizzo più efficiente delle risorse.
Isolamento dei dati. È molto più semplice eseguire aggiornamenti dello schema, perché è interessato solo un singolo microservizio. In un'applicazione monolitica, gli aggiornamenti dello schema possono diventare molto complessi, perché parti diverse dell'applicazione potrebbero toccare tutti gli stessi dati, apportando eventuali modifiche allo schema rischiose.
Problematiche
I vantaggi dei microservizi non sono esenti da problemi. Ecco alcuni degli aspetti da considerare prima di adottare un'architettura di microservizi.
Complessità. Un'applicazione di microservizi ha più parti mobili rispetto all'applicazione monolitica equivalente. Ogni servizio è più semplice, ma l'intero sistema nella sua totalità è più complesso.
Sviluppo e test. La scrittura di un servizio di piccole dimensioni che si basa su altri servizi dipendenti richiede un approccio diverso rispetto alla scrittura di una tradizionale applicazione monolitica o a più livelli. Gli strumenti esistenti non sempre sono progettati per gestire le dipendenze dei servizi. Effettuare il refactoring tra i limiti dei servizi può essere difficile. Può risultare complesso anche testare le dipendenze dei servizi, in particolare quando l'applicazione si evolve rapidamente.
Mancanza di governance. L'approccio decentralizzato alla creazione di microservizi presenta alcuni vantaggi, ma può anche causare problemi. Potrebbero esserci così tanti linguaggi e framework diversi che l'applicazione diventa difficile da gestire. Può essere utile applicare alcuni standard a livello di progetto, senza limitare eccessivamente la flessibilità dei team. Questo vale in special modo per le funzionalità trasversali come la registrazione.
Congestione e latenza di rete. L'uso di molti servizi granulari di dimensioni ridotte può comportare una maggiore comunicazione tra i servizi. Inoltre, se la catena delle dipendenze dei servizi diventa troppo lunga (il servizio A chiama il servizio B, che a sua volta chiama il servizio C...), l'ulteriore latenza può diventare un problema. Sarà necessario progettare le API con attenzione. Evitare API eccessivamente chatte, considerare i formati di serializzazione e cercare posizioni in cui usare modelli di comunicazione asincroni come il livellamento del carico basato su coda.
Integrità dei dati. Ogni microservizio è responsabile della persistenza dei propri dati. Di conseguenza, la coerenza dei dati tra più servizi può essere una sfida. Servizi diversi persistono i dati in momenti diversi, usando tecnologie diverse e con livelli di successo potenzialmente diversi. Quando più di un microservizio è coinvolto nella persistenza di una data nuova o modificata, è improbabile che la modifica completa dei dati possa essere considerata una transazione ACID. Al contrario, la tecnica è più allineata a BASE (Fondamentalmente disponibile, stato soft e infine coerente). Implementare la coerenza finale dove possibile.
Gestione. Per una corretta implementazione dei microservizi è necessaria una conoscenza avanzata dei concetti DevOps. La registrazione correlata tra i servizi può risultare complessa. In genere, la registrazione deve correlare più chiamate ai servizi per una singola operazione utente.
Controllo delle versioni. Gli aggiornamenti di un servizio non devono interrompere i servizi che dipendono da esso. Potrebbero venire aggiornati più servizi in un determinato momento, quindi senza un'attenta progettazione si potrebbero verificare problemi di compatibilità con le versioni precedenti o successive.
Competenze. I microservizi sono sistemi altamente distribuiti. Valutare attentamente se il team ha le competenze e l'esperienza necessarie.
Procedure consigliate
Modellare i servizi attorno al dominio aziendale.
Decentralizzare tutti gli elementi. I singoli team sono responsabili della progettazione e della creazione dei servizi. Evitare di condividere schemi di dati o codice.
L'archiviazione dei dati dovrebbe essere privata per il servizio proprietario dei dati. Usare l'archiviazione migliore per ogni servizio e tipo di dati.
I servizi comunicano attraverso API ben progettate. Evitare la divulgazione dei dettagli dell'implementazione. Le API dovrebbero modellare il dominio, non l'implementazione interna del servizio.
Evitare l'accoppiamento tra servizi. Le cause dell'accoppiamento includono schemi del database condivisi e protocolli di comunicazione rigidi.
Delegare al gateway le questioni trasversali, come l'autenticazione e la terminazione SSL.
Non comunicare al gateway le informazioni di dominio. Il gateway dovrebbe gestire e instradare le richieste client senza dover necessariamente conoscere le regole business o la logica di dominio. In caso contrario, il gateway diventa una dipendenza e può causare l'accoppiamento tra servizi.
I servizi dovrebbero avere un regime di controllo libero e un'elevata coesione funzionale. Le funzioni che potrebbero essere modificate contemporaneamente devono essere inserite in pacchetto e distribuite insieme. Se si trovano in servizi separati, tali servizi finiranno per risultare strettamente accoppiati, perché una modifica in un servizio richiederà l'aggiornamento dell'altro servizio. Le comunicazioni eccessivamente "frammentate" tra due servizi possono essere un sintomo di accoppiamento stretto e bassa coesione.
Isolare gli errori. Usare strategie di resilienza per impedire che gli errori all'interno di un servizio si propaghino. Vedere Modelli di resilienza e Progettazione di applicazioni affidabili.
Passaggi successivi
Per indicazioni dettagliate per la creazione di un'architettura di microservizi in Azure, vedere Progettazione, creazione e gestione di microservizi in Azure.