Cloister → gestione semplice del cluster OTP

Quasi tutte le applicazioni aziendali di successo prima o poi entrano in una fase in cui è necessario un ridimensionamento orizzontale. In molti casi, puoi semplicemente avviare una nuova istanza e ridurre il carico medio. Ma ci sono anche casi meno banali in cui dobbiamo garantire che i diversi nodi si conoscano e distribuiscano attentamente il carico di lavoro.

Cloister → gestione semplice del cluster OTP

Si è rivelato così fortunato Erlang, che abbiamo scelto per la sua piacevole sintassi e per il clamore che lo circonda, ha un file di prima classe supporto per sistemi distribuiti. In teoria, questo sembra del tutto banale:

Il passaggio dei messaggi tra processi su nodi diversi, nonché tra collegamenti e monitor, è trasparente […]

In pratica, tutto è un po’ più complicato. Distribuito Erlang è stato sviluppato quando "container" significava una grande scatola di ferro per la spedizione, e "docker" era semplicemente sinonimo di scaricatore di porto. IN IP4 c'erano molti indirizzi non occupati, le interruzioni della rete erano solitamente causate da topi che masticavano il cavo e il tempo di attività medio del sistema di produzione veniva misurato in decenni.

Ora siamo tutti incredibilmente autosufficienti, confezionati e distribuiti Erlang in un ambiente in cui gli indirizzi IP dinamici vengono distribuiti in base al principio di grande casualità e i nodi possono apparire e scomparire secondo il capriccio del tallone sinistro dello scheduler. Per evitare pile di codice standard in ogni progetto che esegue un file distribuito Erlang, per combattere l'ambiente ostile, è necessario aiuto.

Nota: Sono consapevole che esiste libcluster. È davvero fantastico, ha più di mille stelle, l'autore è famoso nella comunità e tutto il resto. Se i metodi offerti da questo pacchetto per creare e mantenere un cluster ti bastano, sono felice per te. Sfortunatamente, mi serve molto di più. Voglio controllare l'assetto nel dettaglio e non essere uno spettatore esterno nel teatro della riorganizzazione del cluster.

Requisiti

Ciò di cui personalmente avevo bisogno era una libreria che assumesse la gestione del cluster e avesse le seguenti proprietà:

  • lavoro trasparente con un elenco di nodi codificato e rilevamento dinamico attraverso i servizi Erlang;
  • callback completamente funzionale per ogni modifica della topologia (nodo lì, nodo qui, instabilità della rete, divisioni);
  • interfaccia trasparente per l'avvio di un cluster con nomi lunghi e brevi, come con :nonode@nohost;
  • Supporto Docker pronto all'uso, senza dover scrivere il codice dell'infrastruttura.

Quest'ultimo significa che dopo aver testato l'applicazione localmente in :nonode@nohosto in un ambiente distribuito artificialmente utilizzando test_cluster_task, voglio solo correre docker-compose up --scale my_app=3 e guarda come esegue tre istanze nella finestra mobile senza alcuna modifica al codice. Voglio anche applicazioni dipendenti come mnesia - quando la topologia cambia, dietro le quinte ricostruiscono il cluster in tempo reale senza alcun ulteriore kick da parte dell'applicazione.

Chiostro non doveva essere una biblioteca capace di tutto, dal supporto di un cluster alla preparazione del caffè. Non si tratta di una soluzione miracolosa che mira a coprire tutti i casi possibili, o ad essere una soluzione accademicamente completa, nel senso che i teorici di CS mettere in questo termine. Questa libreria è progettata per avere uno scopo molto chiaro, ma svolge perfettamente il suo lavoro non troppo grande. Questo obiettivo sarà quello di fornire una completa trasparenza tra l’ambiente di sviluppo locale e un ambiente elastico distribuito pieno di contenitori ostili.

Approccio scelto

Chiostro è concepito per essere eseguito come un'applicazione, sebbene gli utenti avanzati possano lavorare manualmente con l'assemblaggio e la manutenzione del cluster eseguendo direttamente Cloister.Manager nell'albero del supervisore dell'applicazione di destinazione.

Quando eseguita come applicazione, la libreria si basa su config, da cui si leggono i seguenti valori fondamentali:

config :cloister,
  otp_app: :my_app,
  sentry: :"cloister.local", # or ~w|n1@foo n2@bar|a
  consensus: 3,              # number of nodes to consider
                             #    the cluster is up
  listener: MyApp.Listener   # listener to be called when
                             #    the ring has changed

I parametri sopra indicati significano letteralmente quanto segue: Chiostro utilizzato per l'applicazione OTP :my_appusi scoperta del servizio erlang per connettere i nodi, almeno tre, e MyApp.Listener modulo (implementazione @behaviour Cloister.Listener) è configurato per ricevere notifiche sulle modifiche alla topologia. Una descrizione dettagliata della configurazione completa è disponibile in documentazione.

Con questa configurazione, l'applicazione Chiostro volontà lancio per fasi, ritardando il processo di avvio dell'applicazione principale fino al raggiungimento del consenso (tre nodi sono collegati e connessi, come nell'esempio sopra). Ciò offre all'applicazione principale l'opportunità di presumere che all'avvio il cluster sia già disponibile. Ogni volta che cambia la topologia (ce ne saranno molti, perché i nodi non si avviano in modo completamente sincrono), verrà chiamato il gestore MyApp.Listener.on_state_change/2. La maggior parte delle volte eseguiamo un'azione quando riceviamo un messaggio di stato %Cloister.Monitor{status: :up}, che significa: "Ciao, il cluster è assemblato".

Nella maggior parte dei casi, installazione consensus: 3 è ottimale perché anche se ci aspettiamo che più nodi si connettano, il callback andrà a buon fine status: :rehashingstatus: :up su qualsiasi nodo appena aggiunto o rimosso.

Quando si avvia in modalità sviluppo, è sufficiente impostare consensus: 1 и Chiostro salterà volentieri l'attesa per l'assemblaggio del cluster quando vedrà :nonode@nohostO :node@hostO :[email protected] - a seconda di come è stato configurato il nodo (:none | :shortnames | :longnames).

Gestione delle applicazioni distribuite

Le applicazioni distribuite non nel vuoto di solito includono dipendenze distribuite, come mnesia. Per noi è facile gestire la riconfigurazione dallo stesso callback on_state_change/2. Ecco, ad esempio, una descrizione dettagliata di come riconfigurare mnesia al volo documentazione Chiostro.

Il vantaggio principale dell'utilizzo Chiostro è che esegue tutte le operazioni necessarie per ricostruire il cluster dopo una modifica della topologia sotto il cappuccio. L'applicazione funziona semplicemente in un ambiente distribuito già predisposto, con tutti i nodi collegati, indipendentemente dal fatto che conosciamo in anticipo gli indirizzi IP e quindi i nomi dei nodi, oppure che siano stati assegnati/modificati dinamicamente. Ciò non richiede assolutamente alcuna impostazione speciale di configurazione della finestra mobile e dal punto di vista di uno sviluppatore di applicazioni non c'è differenza tra l'esecuzione in un ambiente distribuito o l'esecuzione in uno locale. :nonode@nohost. Puoi leggere di più a riguardo in documentazione.

Sebbene la gestione complessa delle modifiche alla topologia sia possibile tramite un'implementazione personalizzata MyApp.Listener, potrebbero sempre esserci casi limite in cui le limitazioni della libreria e i pregiudizi di configurazione si rivelano i pilastri dell'implementazione. Va bene, prendi semplicemente quanto sopra libcluster, che è più generico o addirittura gestire autonomamente il cluster di basso livello. L'obiettivo di questa libreria di codici non è coprire tutti gli scenari possibili, ma utilizzare lo scenario più comune senza inutili complicazioni e ingombranti operazioni di copia e incolla.

Nota: a questo punto nell'originale c'era la frase "Happy clustering!", e Yandex, con cui traduco (non devo sfogliare i dizionari da solo), mi ha offerto l'opzione "Happy clustering!" Forse è impossibile immaginare una traduzione migliore, soprattutto alla luce dell’attuale situazione geopolitica.

Fonte: habr.com

Aggiungi un commento