Microservizi: cosa sono, i pro e i contro
L’origine del termine “microservizio” non è facile da rintracciare. Nell’ultimo decennio, tuttavia, la maggioranza delle aziende ha adottato un approccio allo sviluppo e alla gestione delle applicazioni passando da architetture monolitiche ad abbracciare i microservizi.
In breve, “architettura a microservizi” è il termine che descrive la pratica di suddividere un’applicazione in una serie di parti più piccole e specializzate, ciascuna delle quali comunica con le altre attraverso interfacce comuni come API e interfacce REST – relativamente stabili – per creare un’applicazione più grande.
In generale ogni microservizio gestisce il proprio database, genera i propri log e gestisce l’autenticazione dell’utente. Questo di solito significa anche che sono coinvolti i container a livello di gestione e operatività.
È una pratica in netto contrasto con il vecchio modello monolitico che prevede di creare applicazioni come singola entità su un server supportato da un singolo database relazionale. Sebbene l’idea di base di disporre di componenti software discreti non sia nuova, il modo in cui i microservizi vengono implementati li rende una base naturale per le moderne applicazioni basate su cloud.
L’approccio più moderno dei microservizi porta con sé anche un cambio di cultura per i team di sviluppo, con team altamente specializzati che dialogano regolarmente con i team di prodotto, con uno spirito di collaborazione che abbraccia gli stili devops/agile per la continuous delivery.
Quando un software si considera un microservizio?
Il “micro” nei microservizi implica che si tratta di piccole applicazioni. A volte questo è vero, ma le dimensioni in sé e per sé non sono fondamentali. Un modo migliore di pensare ai microservizi è dire che dovrebbero essere grandi quanto basta per fare una cosa specifica o risolvere un problema particolare. Tale problema dovrebbe essere concettuale, non tecnico. Come afferma Microsoft, “I microservizi dovrebbero essere progettati in base alle capacità aziendali, non a livelli orizzontali come l’accesso ai dati o la messaggistica”.
Pertanto, la funzionalità interna di un singolo microservizio può essere ottimizzata o radicalmente aggiornata senza influire sul resto del sistema. Questo a sua volta si sposa con il metodo con cui i team devops cercano di operare: se le funzioni specifiche di un’applicazione più grande sono segmentate in pezzi di codice discreti e indipendenti, è più facile praticare la filosofia devops di Continuous Integration/Continuous Delivery (integrazione continua e rilasci continui). Inoltre, se le API sono ben definite i microservizi sono facili da testare automaticamente.
Architettura dei microservizi contro architettura monolitica
Si sente spesso parlare di microservizi in termini di “architettura a microservizi”. Questa espressione comprende non solo i microservizi stessi, ma anche componenti per la gestione e la scoperta di servizi, nonché un gateway API che gestisca la comunicazione tra microservizi e il mondo esterno.
Una “applicazione monolitica” è l’opposto di ciò che i microservizi sono. È un modo per definire un’applicazione in cui tutto il codice è contenuto in un singolo, grande file eseguibile binario. Un’applicazione monolitica è più difficile da ridimensionare e più difficile da migliorare. Ma poiché è costruito come una singola applicazione coesiva, non richiede strumenti specifici di gestione propri di un’architettura a microservizi.
Definire i confini di un microservizio
Facciamo un passo indietro per un momento alla definizione data: i microservizi dovrebbero fare una cosa specifica. È facile a dirsi, ma in pratica la funzionalità è spesso intrecciata e tracciare confini è più difficile di quanto sembri. L’analisi del dominio e la progettazione guidata dal dominio sono gli approcci teorici che devono aiutare gli sviluppatori a separare il task generale in singoli problemi che un microservizio può risolvere. Questo processo, delineato in una serie illuminante di post sul blog di Microsoft, prevede di creare un modello astratto del dominio aziendale e, in questo processo, scoprire i contesti delimitati che raggruppano funzionalità che interagiscono con il mondo in un modo specifico.
Ad esempio, si potrebbe avere un contesto delimitato per la spedizione e un altro per la contabilità. Un oggetto fisico del mondo reale ha un prezzo (che riguarda la contabilità) e un indirizzo di destinazione (che riguarda le spedizioni), ma i contesti delimitati rappresentano modi specifici in cui l’applicazione pensa e interagisce con quegli oggetti. Ogni microservizio dovrebbe esistere interamente all’interno di un singolo contesto delimitato, sebbene alcuni di essi possano aver bisogno di più di un microservizio.
Microservizi vs. architettura orientata ai servizi vs. Web services
Quanto fin qui descritto dovrebbe suonare familiare a chi è nel ramo IT da un po’ di tempo. L’idea di piccoli programmi individuali che lavorano insieme potrebbe ricordare sia la SOA (Service Oriented Architecture, architettura orientata ai servizi) sia i Web services, due parole molto in voga negli inebrianti giorni del Web 2.0, dopo gli anni 2000. Sebbene in un certo senso non c’è davvero nulla di nuovo sotto il sole, ci sono importanti distinzioni tra questi concetti e quello di microservizio. Datamation presenta una buona ripartizione delle differenze, ma eccone una versione breve:
- In un’architettura orientata ai servizi, i singoli componenti sono accoppiati in modo relativamente stretto, spesso condividendo risorse come l’archiviazione e comunicano attraverso un software specializzato chiamato Enterprise Storage Bus.
- I microservizi sono più indipendenti, condividono meno risorse e comunicano tramite protocolli più leggeri. Vale la pena notare che i microservizi sono nati dall’ambiente SOA e sono talvolta considerati una specie di SOA o successori del concetto.
- Un Web service è un insieme di funzionalità pubblicamente accessibili a cui altre applicazioni possono accedere tramite il Web; probabilmente l’esempio più diffuso è Google Maps, che il sito Web di un ristorante potrebbe incorporare per fornire indicazioni ai clienti. Questa è una connessione molto più libera rispetto a quelle che si trovano in un’architettura di microservizi.
Comunicazione con i microservizi
Uno slogan che si sente spesso ripetere riguardo alle architetture a microservizi è che dovrebbero avere “endpoint intelligenti e connessioni stupide”. In altre parole, i microservizi dovrebbero mirare a utilizzare metodi di comunicazione di base e consolidati anziché richiedere un’integrazione complessa e rigorosa. Come notato, questa è un’altra cosa che distingue i microservizi dalla SOA.
In generale, la comunicazione tra microservizi dovrebbe essere asincrona, nel senso che i thread di codice non rimangono bloccati in attesa di ottenere una risposta. Si possono ancora usare protocolli di comunicazione sincroni come HTTP, anche se nelle architetture a microservizi sono diffusi protocolli asincroni come AMQP (Advanced Message Queuing Protocol). Questo tipo di accoppiamento libero rende un’architettura a microservizi più resiliente al disservizio di singoli componenti o parti della rete, cosa che rappresenta un vantaggio chiave.
Microservizi, Java, Spring Boot e Spring Cloud
Alcuni dei primi lavori nel campo dei microservizi sono nati all’interno della comunità Java; Martin Fowler fu uno dei primi sostenitori. In una conferenza Java del 2012 in Polonia ha fatto una delle più importanti presentazioni iniziali sull’argomento, intitolata “Micro services – Java, the Unix Way“. Fowler ha raccomandato di applicare anche allo sviluppo Java i principi che hanno guidato lo sviluppo delle prime applicazioni Unix negli anni ’70 (“Scrivi programmi che facciano una cosa e la facciano bene. Scrivi programmi che lavorino bene insieme”).
Come risultato di ciò, oggi ci sono molti framework Java che consentono di creare microservizi. Uno dei più popolari è Spring Boot, che è specificamente progettato per i microservizi. Boot viene poi esteso da Spring Cloud, che come suggerisce il nome, consente di distribuire tali servizi anche sul cloud. Pivotal Software, lo sviluppatore di Spring, ha un buon tutorial per iniziare a sviluppare microservizi usando questi framework.
Microservizi e contenitori: Docker, Kubernetes e oltre
La tecnologia di base che di recente ha più contribuito al successo dei microservizi è quella dei container. Un container è simile a un’istanza di macchina virtuale, ma invece di includere un intero sistema operativo autonomo, un container è solo uno spazio utente isolato che utilizza il kernel del sistema operativo host ma mantiene il codice in esecuzione autonomo al suo interno. I container sono quindi molto più piccoli delle macchine virtuali e sono facili da distribuire rapidamente, localmente o nel cloud, e possono essere scalati facilmente verso l’alto o verso il basso per soddisfare la domanda e le risorse disponibili.
Il vantaggio dei container per quanto riguarda i microservizi dovrebbe essere ovvio: ogni singolo microservizio può essere eseguito nel proprio contenitore, il che riduce significativamente le spese generali di gestione dei servizi. La maggior parte delle implementazioni di container dispone di strumenti di orchestrazione complementari che automatizzano l’implementazione, la gestione, il ridimensionamento, il networking e la disponibilità di applicazioni basate su container. È la combinazione di microservizi piccoli e facili da costruire e contenitori facili da distribuire che rende possibile la filosofia DevOps. Esistono diverse implementazioni del concetto di container, ma di gran lunga il più popolare è Docker, che è generalmente associato a Kubernetes come piattaforma di orchestrazione.
Spring, sebbene popolare, è legato alla piattaforma Java. I sistemi basati su container, d’altra parte, sono poliglotti: qualsiasi linguaggio di programmazione supportato dal sistema operativo può essere eseguito in un container, il che offre maggiore flessibilità ai programmatori. In effetti, un grande vantaggio dei microservizi è che ogni singolo servizio può essere scritto in qualunque lingua abbia senso o con cui gli sviluppatori sono più a proprio agio. In effetti, un servizio potrebbe essere completamente ricostruito in un nuovo linguaggio senza influire sul sistema nel suo complesso, purché le sue API rimangano stabili e retrocompatibili. DZone ha un articolo che discute i pro e i contro di Spring Cloud vs. Kubernetes per i microservizi.
Modelli di progettazione di microservizi
Indipendentemente dalla lingua usata per sviluppare microservizi, bisognerà affrontare problemi che altri sviluppatori hanno già incontrato. I modelli di progettazione sono soluzioni formalizzate e astratte a problemi ricorrenti nell’informatica e alcuni di essi sono specifici per i microservizi. Devopedia ne ha una grande lista, che include:
Service registry: per la connessione dei client alle istanze di microservizi disponibili
Circuite breaker: per impedire che servizi che non funzionano vengano chiamati ripetutamente
Fallback: per fornire un’alternativa a un servizio che non funziona
Sidecar: per fornire un servizio ausiliario al container principale, ad esempio per la registrazione, la sincronizzazione dei servizi o il monitoraggio
Adapter: per standardizzare o normalizzare l’interfaccia tra il container principale e il mondo esterno
Ambassador: per connettere il container principale al mondo esterno, ad esempio per il proxy delle connessioni localhost a connessioni esterne
Microservizi e cloud: AWS, Azure e Google
Come notato sopra, uno dei vantaggi dell’utilizzo dei container è che possono essere facilmente implementati nel cloud, dove sono disponibili risorse di calcolo flessibili in modo da poter massimizzare l’efficienza dell’applicazione.
Come si può immaginare, i principali fornitori di cloud pubblico più che pronti a mettere a disposizione le loro piattaforme per eseguire le app basate su microservizi. Per ulteriori informazioni, si consultino le risorse di Amazon, Microsoft e Google.
I pro dei microservizi
L’approccio dei microservizi ha guadagnato trazione nell’era delle applicazioni basate su cloud e web. I suoi esponenti più noti sono aziende nate in questo mondo: Netflix, Spotify, ASOS ed Expedia, per citarne alcune. Anche aziende più tradizionali hanno scelto i microservizi, abbandonando i loro monoliti di codice legacy.
I driver da modificare sono sostanzialmente gli stessi per le aziende: coordinamento delle release tra i team, dipendenze del database, singoli punti di errore, modifiche che influiscono negativamente sugli altri team di prodotto, rendere disponibili le funzionalità ai partner tramite le API.
Consideriamo l’esempio della BBC. La storica emittente radio-televisiva si è rivolta ad Amazon Web Services (AWS) quando ha deciso di spostare in cloud la sua piattaforma video on-demand.
In occasione della conferenza AWS re:Invent del 2017, il responsabile dell’architettura Stephen Goodwin ha spiegato che iPlayer è stato convertito nell’infrastruttura cloud pubblica di AWS nel 2012, e successivamente l’azienda è passata ai microservizi.
“In realtà il sistema è composto da 30 microservizi separati, con messaggi che si muovono lungo una catena di servizi per passare attraverso il flusso di lavoro“, ha affermato Goodwin.
Un altro esempio è il sito di comparazione prezzi Comparethemarket.com. Alla conferenza MongoDB World nel 2016, Matt Collinge, associate director of technology and architecture dell’azienda, ha esaminato i pro e i contro dei microservizi, sulla base della propria esperienza.
“I grandi servizi possono portare a grandi fallimenti: se una applicazione monolitica non funziona, l’azienda non fa soldi. Nel mondo dei microservizi, se un servizio smette di funzionare non blocca l’intera azienda”, ha dichiarato Collinge. “I microservizi guidano l’innovazione e accorciano il ciclo di costruzione, test, apprendimento. Gli sviluppatori si sentono più propensi a sperimentare e liberi di costruire cose che non devono durare dieci anni“.
Inoltre offre ai team maggiore flessibilità. “Ogni team può avere il proprio backlog di modifica, scalabilità e rilascio indipendente, consentendo all’azienda nel suo complesso di muoversi più velocemente“, ha sottolineato Collinge.
I contro dei microservizi
Questo non vuol dire che i microservizi siano perfetti. La complessa rete di dipendenze creata da un’architettura a microservizi può causare problemi di complessità.
In un post piuttosto critico del 2014, il già citato Martin Fowler – che ha contribuito alla definizione del concetto di microservizio – scriveva: “Il problema principale nel cambiare un monolite in microservizi consiste nel cambiare il modello di comunicazione“.
“Un altro problema è che se i componenti non sono sviluppati in modo pulito, tutto quello che si sta facendo è spostare la complessità dall’interno di un componente alle connessioni tra i componenti“, proseguiva Fowler. “Non solo questo distribuisce la complessità, ma la sposta dove è meno esplicita e più difficile da controllare“.
Le cose sono andate avanti da allora, ma ciò non significa che i microservizi siano la scelta giusta per ogni azienda.
“Bisogna investire tempo nella progettazione: limitarsi a spezzare un’applicazione monolitica in microservizi non basta a migliorarla”, ha sottolineato Collinge di Comparethemarket.com. “Se i pezzi sono strettamente accoppiati, si ottengono semplicemente microservizi accoppiati, ovvero un monolite distribuito, che è situazione meno auspicabile“.
Segment, startup specializzata in gestione dati, ha dichiarato a Computerworld che il passaggio ai microservizi ha creato nuovi tipi di code di eventi, che si sono formate per ogni singola destinazione e servizio dell’API partner. Questo significa che gli sviluppatori si sono presto trovati sommersi dalla complessità.
“La manutenzione è diventata un grosso problema per gli sviluppatori: la modifica di ciascuno di questi servizi richiedeva più sviluppatori dedicati e più giorni di lavoro per i test e la distribuzione”, ha spiegato Alex Noonan, ingegnere del software che ha guidato il progetto di Segment. “Era diventato un onere enorme, quindi abbiamo deciso di non apportare modifiche che non fossero strettamente necessarie“.
Alla fine Segment è tornata a un’architettura monolitica, facendo confluire tutti i microservizi nel progetto Centrifuge, un unico sistema di consegna di eventi che la società stava sviluppando.