L’atomizzazione applicativa della logica a microservizi

L’atomizzazione applicativa della logica a microservizi

Il modello dei microservice ha conquistato lo sviluppo per il cloud e si propone anche per la rivisitazione delle applicazioni tradizionali. I vantaggi in effetti sono molti, ma non mancano le complessità

Autore: Francesco Pignatelli



Il concetto dei microservizi è per molti versi l’evoluzione più interessante che abbia toccato lo sviluppo applicativo negli ultimi anni. È un'evoluzione legata in particolare al mondo cloud, anche se l’approccio in sé è più generico, e si associa anche a una concezione più moderna dello sviluppo stesso, nell’ottica delle tanto citate metodologie “agili”. E' anche un modello di sviluppo non sempre semplice da gestire e che non tutte le aziende riescono a fare proprio. Per più di un motivo. Il modello dei microservizi scompone un’applicazione in una collezione di servizi che svolgono ciascuno una funzione specifica - ecco perché “micro” - e che insieme portano al risultato voluto. Un po’ come un’orchestra suona bene perché ciascuno dei suoi componenti sa perfettamente cosa fare e quando, così un’applicazione si suddivide in un gruppo di funzioni mirate che si attivano solo quando necessario.

Lo sviluppo è quindi concettualmente diverso dal modello classico: si identificano le singole funzioni che l’applicazione deve avere e le si traducono in microservizi, che sono autonomi e gestiscono ciascuno le proprie risorse (ad esempio un proprio database). Dal dialogo tra i microservizi “emerge” l’applicazione, senza che questa esista come elemento monolitico. Pensiamo ad esempio allo sviluppo di un’applicazione per prenotazioni aeree. Potrebbe essere composta da un servizio che identifica l’utente, uno che interroga i database delle linee aeree per trovare il volo che cerchiamo, uno che gestisce i pagamenti, uno che genera i biglietti e via dicendo, arrivando anche a decine di elementi diversi. Ciascuno di questi servizi scambia ovviamente informazioni con gli altri in maniera coordinata ma resta autonomo. Tanto che in questa sinergia di servizi ce ne può anche essere qualcuno non sviluppato da noi ma da altri (per allacciarsi a un altro tema popolare: la API economy).

Perché piacciono i microservice
Il vantaggio principale dell’approccio a microservizi sta nella loro indipendenza, che semplifica lo sviluppo successivo, la manutenzione e la scalabilità dell’applicazione. Purché non cambi il modo in cui si mostra agli altri (via API, tecnicamente) e comunica con essi (via Rest), un microservizio può essere modificato come e quando si vuole, usando i linguaggi e le piattaforme migliori in quel momento. Si possono quindi migliorare parti significative di un’applicazione senza preoccuparsi che le modifiche influiscano negativamente sul suo funzionamento complessivo. Il tema della scalabilità è analogo: se una parte specifica di un’applicazione ha bisogno di maggiori risorse, ad esempio perché è aumentato il numero degli utenti e quindi c’è un carico maggiore sulla parte di autenticazione, basta incrementare quelle a disposizione del microservizio collegato, senza dover ripensare la logica di funzionamento globale.

Da questa considerazione si intuisce come la logica dei microservice si sposi perfettamente con la virtualizzazione e in particolare con il modello a container. Un container è il mezzo ideale con cui realizzare un microservizio perché entrambi sono componenti “atomici”. Quando un microservizio deve operare si attivano uno o più container relativi, aumentando o riducendo il numero di istanze attive in funzione di come aumenta o cala il carico di lavoro di quella funzione. Quando il servizio ha esaurito il suo compito i container si disattivano, pronti a entrare nuovamente in gioco alla prossima richiesta. Quello descritto è il modello tipico delle applicazioni cloud-native e infatti un’architettura a microservice si può abilitare con relativa facilità in un ambiente PaaS (Platform-as-a-Service), oggi puntando sui container, in prospettiva, probabilmente, sempre più sui servizi di serverless computing (o FaaS, Functions-as-a-Service).

Un altro collegamento ideale è tra microservizi e sviluppo DevOps. La concezione destrutturata dei microservice si sposa infatti bene con lo sviluppo agile e incrementale: quando vogliamo cambiare o migliorare un determinato aspetto della nostra applicazione non dobbiamo mettere mano a decine di migliaia di linee di codice ma solo a quelle del microservizio coinvolto. Questo permette di introdurre miglioramenti con maggiore frequenza e di implementarli con la ragionevole certezza che le modifiche non metteranno in crisi tutto il sistema, se qualcosa dovesse non funzionare come previsto. Anche le attività di verifica, test e distribuzione del codice modificato sono evidentemente più veloci e meno rischiose.

Il peso della complessità
Come sempre non è tutto oro quello che luccica e anche il modello dei microservizi pone i suoi problemi. Il primo e più evidente è ovvio: è relativamente facile seguire il flusso logico e operativo di un’applicazione tradizionale, lo è molto meno avere una visione integrata e completa di decine o centinaia di microservizi che si attivano e disattivano in continuazione. Possiamo magari avere una visione ad alto livello della nostra applicazione, verificando cioè se funziona come deve nel suo complesso e con le prestazioni che ci aspettiamo, ma scendere poi nel dettaglio non è immediato.

Il tema chiave è quello dell’orchestration dei microservizi: servono i tool per capire in ogni momento quale microservice sta facendo cosa e per verificare che la sinergia tra i vari servizi sia quella corretta. Le piattaforme per l’orchestration ci sono, essenzialmente legate al mondo dei container, la difficoltà sta nel prendere la mano sia con esse sia con l’approccio in generale. Quando qualcosa non va e siamo alla ricerca delle cause, la situazione è meno rosea. Il debug di un complesso di microservizi non è semplice perché non c’è un flusso di codice da seguire: l’esecuzione della nostra applicazione può essere distribuita su sistemi diversi ed è demandata a istanze di container che per loro natura sono temporanee.

Spesso aiuta adottare approcci un po’ creativi nella gestione dei log dei vari sistemi, in modo da poter capire anche a posteriori quale evento ha generato quale condizione. Il problema complementare della gestione delle performance di un’applicazione “destrutturata” è altrettanto complesso. Il tema di fondo non cambia (è sempre la corretta sinergia tra i microservizi) ma sono ancora poche le piattaforme di performance monitoring che si sono adattate al nuovo modello di sviluppo e possono controllare efficacemente le prestazioni di un’architettura modulare. I punti critici dello sviluppo a microservizi peraltro non ne mettono in discussione il modello, che ormai è affermato e ha dimostrato di portare benefici ampiamente superiori agli svantaggi. Vanno però tenuti presente da chi non ha ancora intrapreso questa strada, specie se oltre allo sviluppo di nuove applicazioni cloud-native pensa anche alla conversione di quelle monolitiche che ha già in essere. Non è detto che questa transizione sia sempre possibile o conveniente, proprio perché richiede un ripensamento completo delle logiche applicative.