Si chiama microservice ed è il pattern architetturale del momento. Tutti i vantaggi delle architetture a microservizi, che qualcuno confonde ancora con la SOA. Senza trascurare qualche insidia.

Parlare di microservice (o microservices, “microservizi”) nell’ambito delle architetture software è oggi di gran moda. Diciamo anzi che il modello a microservizi si è affermato come il trend del momento. È la cosa di cui devi parlare, se vuoi risultare interessante. In effetti il paradigma microservice introduce importanti elementi di innovazione nelle metodologie di sviluppo. Tuttavia si tratta di una novità solo in parte, come spesso accade nel magico mondo dell’Information Technology. Una novità che fa della modularizzazione e della separation of concern i propri cavalli di battaglia.

Accoppiamento debole

Il “nuovo” modo di sviluppare un’architettura software parte dall’idea di creare un insieme di servizi accoppiati in modo debole (loosely coupled), che implementano ciascuno le varie business logic di cui il nostro sistema ha bisogno.

Questa definizione, però, non è affatto nuova. Infatti, l’architettura SOA (Service Oriented Architecture) può essere definita più o meno allo stesso modo. Per qualcuno, anzi, microservice è nient’altro che una variante di SOA.

SOA è definita come una collezione di servizi che comunicano gli uni con gli altri. Un servizio, a sua volta, è una funzionalità ben definita e auto contenuta che non dipende dal contesto o dallo stato di altri servizi.

Comunicazioni

Le comunicazioni, dal canto loro, possono essere considerate come semplice passaggio di dati tra un servizio e un altro, oppure possono coinvolgere due o più servizi che coordinano alcune attività.

Senza scendere nei dettagli dell’architettura SOA, si può evincere con facilità che si fa presto a confondere i due costrutti e a relegare il nuovo pattern architetturale microservice come una moda che non porta nulla di nuovo rispetto al passato.

Microservice come sotto-insieme di SOA

Come ha sottolineato lo stesso Martin Fowler in un suo famoso speech al GOTO, probabilmente il miglior modo di distinguere i due pattern è sulla base delle dimensioni. Ebbene sì, a quanto pare le dimensioni contano.

Martin definisce microservice come un sottoinsieme dell’enorme mondo SOA che a sua volta viene spesso indicato e caratterizzato dal bus di comunicazione che permette ai servizi di essere gestiti ed orchestrati.

Il valore aggiunto dai microservices, quindi, è quello di porre un’etichetta su uno ben specifico subset di funzionalità e capacità di SOA.

Possiamo affermare, quindi, che microservice non è una tecnica nuova in assoluto. Tuttavia le sue implicazioni organizzative e gestionali sono un concetto abbastanza nuovo.

Cosa sono i microservice

Le caratteristiche principali di un’architettura a microservice, che ci permetteranno di definire i “confini” di ogni servizio, sono l’alta coesione e il basso accoppiamento.

Entrambe le caratteristiche ci permettono di capire, in prima analisi, cosa dovrebbe contenere un servizio e cosa dovrebbe delegare ad altri servizi.

Scope di un servizio

Un esercizio che ci può fare per capire lo scope di ogni servizio è quello che permette di stabilire innanzi tutto la funzionalità che si vuole implementare e poi decidere quanto la si può isolare rispetto al contesto dell’intero sistema.

Tale esercizio ci porterà a capire che un servizio deve contenere soltanto le funzionalità e gestire i dati per il servizio che dovrà implementare.

Se un servizio ha bisogno troppe volte di chiamarne un altro per scambiare dei dati o per accedere ad altre funzionalità, allora, probabilmente i due servizi vanno integrati.

Al contrario se un servizio si occupa di troppe cose, allora potrebbe essere necessario suddividerlo in più servizi che, eventualmente, ogni tanto, interagiscono attraverso canali di comunicazione generalmente lightweight.

Modelli di comunicazione per microservice

In una siffatta architettura, la comunicazione tra i servizi ricopre un ruolo molto importante. In genere i servizi comunicano attraverso protocolli sincroni come HTTP/REST, oppure asincroni come AMPQ (Advanced Message Queuing Protocol).

Il concetto di microservice non ha a che fare solo con la dimensione di ogni servizio, ma con la necessità di dare allo stesso un ben preciso confine e impatto sulle funzionalità dell’intero sistema.

Vantaggi

Il primo vantaggio di un’architettura a microservizi è quello di mantenere i servizi abbastanza piccoli da essere capiti e gestiti da un team minimo di persone, le quali per inciso, potrebbero non dover conoscere l’intero sistema in cui il loro servizio verrà inserito. Ma microservices è molto più di questo.

Velocità di rilascio del singolo servizio

I veri vantaggi di una siffatta architettura sono soprattutto legati alla possibilità di rilasciare ogni servizio in modo indipendente. È un approccio che si contrappone a quello delle architetture monolitiche, le quali vanno rilasciate nella loro interezza anche solo se si aggiorna una minima funzionalità in qualche suo modulo.

L’accelerazione della frequenza di aggiornamento di ogni singola funzionalità, per esempio, ha spinto Netflix a passare da un’architettura monolitica ai microservices, in modo che si potessero rapidamente rilasciare aggiornamenti su singole funzionalità senza avere impatto sull’intero sistema.

I vantaggi di questo tipo di architettura sono molteplici. Come accennato in precedenza, la velocità nel rilascio di aggiornamenti di una singola funzionalità è maggiore rispetto a quella richiesta per l’intero sistema. Se non altro perché, se ben definiti, i servizi saranno poco coesi. Quindi una modifica in uno di loro non implica cambiamenti negli altri.

Scalare un servizio Vs intera applicazione

Un altro vantaggio dei sistemi che implementano questa architettura è dato dalla possibilità, soprattutto su architetture deployate in cloud, di scalare solo i servizi necessari e non dover gestire cluster, balancing e fault tolerant dell’intero monolite.

Diversi linguaggi per diverse funzionalità

Possiamo inoltre implementare ogni servizio con un linguaggio diverso, andando incontro all’esigenza di utilizzare quello che più si adatta alla specifica funzionalità. È possibile affidarci al consolidato e affidabile Java e soprattutto al framework Spring Boot, per esempio. Oppure utilizzare un linguaggio JavaScript orientato agli eventi e non bloccante come Node.js,eventualmente con l’utilssimo framework NestJS basato su Express e Typescript. O ancora sfruttare il performante Python e le sue svariate librerie che lo rendono versatile per l’implementazione di diversi tipi di funzionalità (Django e Flask per il web, per esempio, o SciPy per la matematica e l’ingegneria).

Svantaggi

Come in ogni cosa, c’è un prezzo da pagare quando si decide di utilizzare un’architettura a microservizi.

Una delle caratteristiche principali di una siffatta architettura è la separation of concern dei servizi. Questa si porta dietro, anche, la separazione delle basi dati a supporto, perché esse rappresenterebbero un meccanismo di accoppiamento. Per esempio, un servizio potrebbe non funzionare se un altro apportasse dei cambiamenti allo schema.

Coerenza dati

La prima e importante implicazione di questa separazione è la consistenza dei dati, perché sarà necessario adottare alcune tecniche particolari e scendere a compromessi, per fare in modo che i dati siano coerenti tra i vari servizi.

Una possibile soluzione, per esempio, potrebbe far uso di messaggi asincroni tra le parti coinvolte, per condividere i dati o utilizzare il Pattern SAGA per gestire eventuali transazioni che implicano più servizi.

Un altro aspetto da tenere in considerazione nasce dalla natura stessa dei servizi. Questi dovranno essere monitorati e gestiti sulla base della loro disponibilità ed efficienza. Ciò implica l’utilizzo di sistemi di Service Discovery, di Monitoring e Circuit Breaker. Supponiamo, per esempio, che un servizio non risponda in tempi accettabili per diverse chiamate successive. Per questo tipo di scenario dovrà essere possibile “aprire il circuito” e fare in modo che quel servizio non venga più chiamato per un certo periodo di tempo. Consul per esempio è un framework che sulla base di un messaggio di keep alive decide se continuare ad instradare le chiamate verso un servizio che non risponde o meno.

Service Discovery

Il Service Discovery può essere implementato in diversi modi. Infatti, sarà possibile utilizzare un framework esterno che permetta ai servizi di registrare “la propria funzionalità” e renderla disponibile agli altri servizi che ne potrebbero aver bisogno. etcd e Consul sono framework costruiti per implementare tale funzionalità. Oppure è possibile definire un meccanismo di “messaggi asincroni” in un topic e lasciare ai servizi interessati a tale messaggio la possibilità di registrarsi su quel topic per gestire la propria business logic.

Conclusioni

L’architettura a microservizi, quindi, se da una parte fornisce delle ottime motivazioni per implementare le nostre soluzioni seguendone il paradigma, dall’altra parte implica una serie di “nuove problematiche” legate all’aumento della complessità della parte Ops che porta con sé.

In questo articolo ho voluto parlare di alcuni concetti base di questa architettura, che richiederebbe, invece, un approfondimento per ogni sua parte, ogni nuovo concetto introdotto e le tecniche utilizzate per cercare di risolvere i problemi che suddetta architettura implica. Ci ritorneremo.