Questa è una domanda molto aperta, ma cercherò di illustrare perché Elixir / Erlang potrebbe essere la migliore piattaforma disponibile per lo sviluppo di sistemi distribuiti (indipendentemente dal fatto che si lavori con microservizi).
Per prima cosa, iniziamo con alcune informazioni di base. Erlang VM e la sua libreria standard sono state progettate in anticipo per la creazione di sistemi distribuiti e questo si vede davvero. Per quanto ne so, è l'unico runtime e VM ampiamente utilizzati nella produzione progettati in anticipo per questo caso d'uso.
applicazioni
Ad esempio, hai già accennato alle "applicazioni". In Erlang / Elixir, il codice è contenuto in applicazioni che:
- vengono avviati e arrestati come unità. Avviare e arrestare il sistema è questione di avviare tutte le applicazioni in esso contenute
- fornire una struttura di directory unificata e un'API di configurazione (che non è XML!). Se hai già lavorato e configurato un'applicazione OTP, sai come lavorare con qualsiasi altra
- contiene il tuo albero di supervisione dell'applicazione, con tutti i processi (per processo intendo "processi VM" che sono thread di calcolo leggeri) e il loro stato
L'impatto di questo design è enorme. Significa che gli sviluppatori Elixir, quando scrivono le applicazioni, hanno un approccio più esplicito a:
- come il loro codice viene avviato e interrotto
- quali sono i processi che fanno parte di un'applicazione e quindi qual è lo stato dell'applicazione
- come questi processi reagiranno e saranno influenzati in caso di crash o quando qualcosa va storto
Non solo, gli strumenti attorno a questa astrazione sono fantastici. Se avete installato Elixir, aprire "iex" e digitare: :observer.start()
. Oltre a mostrare informazioni e grafici sul tuo sistema live, puoi uccidere processi casuali, vedere il loro utilizzo della memoria, lo stato e altro. Ecco un esempio di come eseguirlo in un'applicazione Phoenix:
La differenza qui è che Applicazioni e processi ti danno un'astrazione per ragionare sul tuo codice in produzione . Molti linguaggi forniscono pacchetti, oggetti e moduli principalmente per l'organizzazione del codice senza alcuna riflessione sul sistema di runtime. Se hai un attributo di classe o un oggetto singleton: come puoi ragionare sulle entità che possono manipolarlo? Se hai una perdita di memoria o un collo di bottiglia, come puoi trovare l'entità responsabile?
Se chiedi a qualcuno che gestisce un sistema distribuito, questo è il tipo di intuizione che vogliono, e con Erlang / Elixir hai questo come elemento costitutivo.
Comunicazione
Tutto questo è davvero solo l'inizio. Quando si costruisce un sistema distribuito, è necessario scegliere un protocollo di comunicazione e il serializzatore di dati. Molte persone scelgono HTTP e JSON che, a pensarci bene, è una combinazione molto prolissa e costosa per eseguire quelle che sono veramente chiamate RPC.
Con Erlang / Elixir, hai già un protocollo di comunicazione e un meccanismo di serializzazione fuori dagli schemi. Se vuoi che due macchine comunichino tra loro, devi solo dare loro un nome, assicurarti che abbiano lo stesso segreto e il gioco è fatto.
Jamie ne ha parlato alla Erlang Factory 2015 e di come sono stati in grado di sfruttarlo per costruire una piattaforma di gioco: https://www.youtube.com/watch?v=_i6n-eWiVn4
Se vuoi usare HTTP e JSON, va bene anche questo e librerie come Plug e framework come Phoenix ti garantiranno che sei produttivo anche qui.
Microservices
Finora non ho parlato di microservizi. Questo perché, fino a questo punto, non contano davvero. Stai già progettando il tuo sistema e i tuoi nodi attorno a processi molto piccoli che sono isolati. Chiamali nanoservizi se vuoi!
Non solo, sono anche impacchettati in applicazioni, che li raggruppano come entità che possono essere avviate e arrestate come unità. Se hai applicazioni A, B e C, e poi vuoi distribuirle come [A, B] + [C] o [A] + [B] + [C], avrai pochissimi problemi nel farlo a causa al loro design intrinseco. O, ancora meglio, se vuoi evitare di aggiungere in anticipo la complessità delle distribuzioni di microservizi al tuo sistema, puoi semplicemente distribuirli tutti insieme nello stesso nodo.
E, alla fine della giornata, se stai eseguendo tutto questo utilizzando il protocollo distribuito di Erlang, puoi eseguirli in nodi diversi e saranno in grado di raggiungerne altri fintanto che ti riferisci a loro {:node@network, :name}
invece di :name
.
Potrei andare oltre ma spero di averti convinto a questo punto. :)