Microservizi. Attenzione: sostanza altamente esplosiva!

Jacopo Freddi coding, soluzioni digitali

 

Cosa sono i microservizi? E come impattano sullo sviluppo e sui risultati per chi li sceglie? Ce lo racconta Jacopo, prendendo spunto da alcuni workshop tematici di approfondimento, come il Codemotion, a cui i nostri sviluppatori partecipano regolarmente per aggiornarsi su novità e per approfondire i linguaggi.

 

Architettura a Microservizi

L’architettura a microservizi (microservices architecture o MA) è l’hype del momento: tutti i grandi attori nel mercato dei servizi web (Amazon, Atlassian e Netflix per citarne alcuni) hanno, in varia misura, adottato questa soluzione nel loro workflow.
I benefici di questa architettura sono evidenti:

  • è possibile applicare alla lettera il principio di Singola Responsabilità (“fai una cosa sola, e falla bene!”): ogni microservizio assolve a un pezzo circoscritto della Business Logic del sistema e può essere ottimizzato per quel task senza impattare gli altri microservizi;
  • è altamente scalabile a livello di sviluppo: essendo separati per definizione, i microservizi che compongono un sistema possono essere sviluppati e mantenuti da team diversi senza che i colli di bottiglia di un team rallentino gli sviluppi degli altri. Spinto all’estremo, questo punto suggerisce che i team potrebbero anche sviluppare microservizi diversi in linguaggi diversi o piattaforme diverse;
  • è altamente scalabile a livello di deploy: i microservizi sono facilmente replicabili per far fronte a un aumento di domanda e se combinati a uno sviluppo container-oriented risultano estremamente semplici da testare e aggiornare;
  • i microservizi sono facilmente rimpiazzabili: se un microservizio inizia a non funzionare più bene, potrebbe essere più semplice e conveniente svilupparne uno nuovo che rifattorizzare quello esistente;

E la lista potrebbe continuare. Vedendo questi vantaggi a chiunque verrebbe la tentazione di impostare un’architettura a microservizi per il suo prossimo progetto, ma il bravo informatico sa che nessuna tecnologia può incarnare il mitico “martello che può piantare qualsiasi chiodo” ed ogni medaglia ha il suo rovescio…

 

Maneggiare con cura!

In effetti l’architettura a microservizi non è priva di rischi, anzi: uno sviluppatore impreparato potrebbe trarre più danno che beneficio da questa infrastruttura.

In primo luogo, l’architettura a microservizi non elimina la complessità di un sistema, ma la sposta dal codice all’infrastruttura di rete: ogni microservizio è relativamente piccolo e semplice, ma essendoci tanti attori nel sistema non è più scontato gestirne la complessità a livello di protocollo di comunicazione, sicurezza e flusso logico.

Alcune componenti relativamente semplici da implementare in un sistema monolitico diventano ostacoli delicati da gestire in un ambiente distribuito: esemplare è il caso dei log, che se non ben progettati rischiano di essere illeggibili nel momento del bisogno (ammesso che lo sviluppatore riesca a trovarli). La decentralizzazione dei server comporta ulteriori problematiche di cui tener conto, come il fuso orario delle entrate di log.

Inoltre la libertà di adottare diverse tecnologie per ogni nodo, se abusata, potrebbe portare un team irresponsabile ad adottare tecnologie poco conosciute portando instabilità nel sistema, aumentando i costi di manutenzione e, senza un protocollo di comunicazione stabile e condiviso tra team, aumenterebbe inutilmente la già alta complessità della gestione della rete.

Un altro punto da tenere in considerazione è la testabilità. In un contesto monolitico si segue la tipica piramide di test, procedendo dai test di unità sulle singole componenti fino ai test di UI / UX dell’intero sistema. In un contesto distribuito, non volendo rinunciare ai test automatici, sono necessari ulteriori accorgimenti per ottenere lo stesso margine di sicurezza. Avendo forzato la separazione del problema eseguire test di unità su un singolo microservizio è più immediato, ma non più sufficiente. È infatti preferibile testare il singolo microservizio anche quando “immerso nell’ecosistema”, senza utilizzare vere istanze per gli altri attori. Questo tipo di test richiede cura particolare nella costruzione di fakes sufficientemente accurati per ogni servizio e, di conseguenza, extra effort nella sua manutenzione.

Infine, ogni microservizio dev’essere configurato separatamente (connessione al database, struttura del filesystem, SDK di supporto), operazione time consuming ed error-prone per sviluppatori inesperti. L’utilizzo di containers mitiga molto questo ostacolo, ma non lo elimina del tutto.

 

Le buone regole per non rischiare di scottarsi

Questa lista non estensiva di caveat non mira tanto a dissuadere dall’utilizzo dei microservizi, quanto a raccogliere alcuni dei punti più importanti da tenere in considerazione quando si sviluppa in quest’ottica. È comunque possibile prendere alcuni accorgimenti per ridurre al minimo gli errori più comuni e passare più tempo a creare business value

  • Scrivere test fin da subito: i benefici di questo punto sono lampanti e troppi per essere elencati puntualmente.
  • Usare il più possibile componenti “out of the box”. Basare il proprio servizio su una PaaS (Platform as a Service) permette di ridurre al minimo i rischi di incompatibilità del software di base, riduce i tempi di configurazione e spesso offre soluzioni standard per gestire alcuni problemi tipici degli ambienti distribuiti.
  • Usare un unico protocollo di comunicazione tra i servizi, possibilmente standard (SOAP, REST, …). Se possibile, tenere in considerazione i costi nascosti di ogni protocollo quando lo si sceglie (complessità di elaborazione, overhead, diffusione…).
  • Se possibile, affidarsi a servizi di orchestrazione completi e affermati; ad esempio, al Codemotion di Milano 2017 Microsoft ha presentato Service Fabric. Un buon servizio di orchestrazione non deve limitare il suo supporto a specifiche tecnologie, offre soluzioni solide e intuitive per la gestione di log, alert e balancing e una dashboard espressiva.