Cloister → gestione semplice del cluster OTP

Praticamente ogni applicazione business di successo arriva, prima o poi, a una fase in cui è necessario scalare orizzontalmente. In molti casi, è sufficiente avviare una nuova istanza e ridurre il carico medio. Ma ci sono situazioni meno banali in cui dobbiamo assicurarci che i nodi diversi siano consapevoli l'uno dell'altro e distribuiscano il carico di lavoro in modo ordinato.

Cloister → gestione semplice del cluster OTP

È andata così bene che erlang, che abbiamo scelto per la sua sintassi gradevole e l'hype attorno ad esso, ha un supporto di prim'ordine per sistemi distribuiti. In teoria, tutto ciò sembra piuttosto banale:

Il passaggio di messaggi tra processi su nodi diversi e tra collegamenti e monitor è trasparente […]

Nella pratica, tutto è un po' più complicato. Distribuito erlang è stato sviluppato quando "container" significava una grande scatola metallica per il trasporto e "docker" era semplicemente sinonimo di portuale. Nel IP4 c'erano molti indirizzi liberi, nei tagli di rete la colpa era spesso di ratti che rosicchiavano i cavi e il tempo medio di operatività di un sistema produttivo si misurava in decenni.

Ora siamo tutti incredibilmente autosufficienti, imballati e stiamo eseguendo un sistema distribuito erlang in un ambiente in cui gli indirizzi IP dinamici vengono distribuiti secondo il grande caso, e i nodi possono apparire e scomparire a piacimento della mano sinistra del pianificatore. Per evitare un ingombro di codice standard in ogni progetto che esegue un sistema distribuito erlang, per affrontare un ambiente ostile, è necessario un aiuto.

Nota: sono consapevole che esiste libcluster. È davvero fantastico, ha più di mille stelle, l'autore è noto nella community, e così via. Se ti bastano i metodi offerti da questo pacchetto per creare e mantenere un cluster, sono felice per te. Purtroppo, ho bisogno di molto di più. Voglio gestire la configurazione nei dettagli e non essere un semplice spettatore nel teatro della riformazione del cluster.

Requisiti

Quello di cui avevo bisogno personalmente era una libreria che gestisse il cluster e avesse le seguenti caratteristiche:

  • funzionamento trasparente sia con un elenco di nodi predefiniti che con la scoperta dinamica tramite servizi erlang;
  • callback completamente funzionale ad ogni cambiamento della topologia (nodo qua, nodo là, instabilità di rete, splitting);
  • interfaccia trasparente per l'avvio di un cluster con nomi lunghi e brevi, proprio come con :nonode@nohost;
  • supporto Docker pronto all'uso, senza la necessità di scrivere codice infrastrutturale.

Questo significa che, dopo aver testato l'applicazione localmente in :nonode@nohost, o in un ambiente artificialmente distribuito tramite test_cluster_task, voglio semplicemente eseguire docker-compose up --scale my_app=3 e vedere come esegue tre istanze in Docker senza alcuna modifica al codice. Voglio anche che le applicazioni dipendenti, come mnesia — quando la topologia cambia, ricostruiscano il cluster in tempo reale senza alcun ulteriore impulso dall'app.

Cloister non è progettato come una libreria capace di tutto: dal supporto al cluster alla preparazione del caffè. Non è una panacea, che mira a coprire tutti i casi possibili, né essere una soluzione accademicamente completa nel senso in cui la intendono i teorici di CS investono in questo termine. Questa libreria è progettata per servire a uno scopo molto chiaro, ma eseguire il suo non troppo grande volume di lavoro in modo perfetto. Questo obiettivo sarà quello di fornire piena trasparenza tra l'ambiente di sviluppo locale e l'ambiente elastico distribuito, pieno di contenitori ostili.

L'approccio scelto

Cloister è previsto che venga eseguito come applicazione, sebbene gli utenti esperti possano lavorare con l'assemblaggio e la manutenzione del cluster manualmente, avviando direttamente Cloister.Manager nella struttura dei supervisori dell'applicazione target.

Quando viene eseguita come applicazione, la libreria si basa su config, da cui legge i seguenti valori principali:

config :cloister,
  otp_app: :my_app,
  sentry: :"cloister.local", # oppure ~w|n1@foo n2@bar|a
  consensus: 3,              # numero di nodi da considerare
                             #    il cluster è attivo
  listener: MyApp.Listener   # listener da chiamare quando
                             #    l'anello è cambiato

I parametri sopra significano letteralmente quanto segue: Cloister è utilizzato per l'applicazione OTP :my_app, utilizza la scoperta dei servizi Erlang per collegare i nodi, almeno tre, e MyApp.Listener modulo (implementante @behaviour Cloister.Listener) è configurato per ricevere notifiche sui cambiamenti nella topologia. Puoi trovare una descrizione dettagliata della configurazione completa in documentazione.

Con questa configurazione, l'applicazione Cloister verrà viene avviata passo dopo passo, rinviando il processo di avvio dell'app principale fino a quando non viene raggiunto un consenso (tre nodi connessi e collegati, come nell'esempio sopra). Questo consente all'app principale di supporre che, una volta avviata, il cluster sia già disponibile. Al momento di ogni cambiamento nella topologia (ce ne saranno molti, poiché i nodi non si avviano in modo completamente sincronizzato), verrà invocato il gestore MyApp.Listener.on_state_change/2. Nella maggior parte dei casi, eseguiamo un'azione quando riceviamo un messaggio con lo stato %Cloister.Monitor{status: :up}, che significa: «Ehi, cluster assemblato».

Nella maggior parte dei casi, impostare consensus: 3 è ottimale, perché anche se ci aspettiamo che si connettano più nodi, il callback passerà attraverso status: :rehashingstatus: :up su qualsiasi nuovo nodo aggiunto o rimosso.

Quando si avvia in modalità di sviluppo, è sufficiente impostare consensus: 1 e Cloister e salterà felicemente l'attesa della costruzione del cluster, vedendo :nonode@nohost, o :node@host, o :node@host.domain — a seconda di come è stato configurato il nodo (:none | :shortnames | :longnames).

Gestione delle applicazioni distribuite

Le applicazioni distribuite non esistono in un vuoto e in genere includono dipendenze distribuite, come mnesia. È facile per noi gestire la loro riconfigurazione dallo stesso callback on_state_change/2. Ecco, per esempio, una descrizione dettagliata di come riconfigurare mnesia a caldo in documentazione Cloister.

Il principale vantaggio dell'utilizzo di Cloister è che esegue tutte le operazioni necessarie per la ricostruzione del cluster dopo la modifica della topologia sotto il cofano. L'applicazione viene semplicemente avviata in un ambiente distribuito già configurato, con tutti i nodi connessi, indipendentemente dal fatto che conosciamo gli indirizzi IP e, quindi, i nomi dei nodi in anticipo, o che siano stati assegnati/cambiati dinamicamente. Ciò non richiede alcuna configurazione speciale di Docker e dal punto di vista dello sviluppatore dell'app, non c'è alcuna differenza tra l'esecuzione in un ambiente distribuito o in locale su :nonode@nohost. Maggiori informazioni possono essere trovate in documentazione.

Nonostante la complessa gestione delle modifiche alla topologia sia possibile attraverso una propria implementazione MyApp.Listener, ci possono essere casi limite in cui queste limitazioni della libreria e un approccio pregiudiziale alla configurazione si rivelino un ostacolo all’implementazione. Va bene, basta prendere quanto sopra menzionato. libcluster, che è più versatile, o anche gestire il cluster di basso livello da soli. L'obiettivo di questa libreria di codice non è quello di coprire tutti gli scenari possibili, ma di sfruttare lo scenario più comune senza dolori inutili e ingombri di copia e incolla.

Nota: in questo punto l'originale conteneva la frase «Happy clustering!», e Yandex, per cui traduco (non posso certo andare a cercare nei dizionari), mi ha suggerito «Sfortunato raggruppamento!». Una traduzione migliore, data la attuale situazione geopolitica, non si potrebbe nemmeno immaginare.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster