Learn

Caratteristiche e vantaggi di Apache ZooKeeper

18 Maggio 2021 - 4 minuti di lettura

Apache ZooKeeper è un software, di proprietà di The Apache Software Fondation, in grado di fornire supporto per la gestione della la sincronizzazione di sistemi distribuiti.

Durante la nostra prima Unconference del 27 Aprile il collega Marco Testa ha dedicato una sessione a questo strumento raccontandoci la sua esperienza: perché adottarlo, quali sono le principali caratteristiche e infine alcune considerazioni dall’esperienza d’utilizzo del servizio.

Buona lettura.

Perché adottare Apache ZooKeeper

Doveste trovarvi a lavorare con un sistema distribuito, composto quindi da una multitudine di servizi ognuno con una sua responsabilità e task da eseguire, potrebbe quanto prima sorgere un problema: come gestire le risorse e il carico di lavoro di ognuno dei microservizi?

Il problema che sta alla base della scelta di ZooKeeper è quindi la seguente: dati n servizi, eleggere un leader. Ovviamente, se per qualsiasi motivo il servizio leader dovesse avere qualche malfunzionamento, un altro servizio dovrebbe subentrare come leader.
Questa però è soltanto una delle problematiche ricorrenti in un’applicazione distribuita. Altre problematiche ricorrenti sono le seguenti:

  • Name Service, ovvero riuscire a trovare un servizio tra i tanti disponibili.
  • Configuration, definire una configurazione condivisa.
  • Group Membership, avere un’idea chiara di quali siano i servizi simili tra loro e quindi raggrupparli così da riconoscerli e classificarli.
  • Message queues, cioè gestire la modalità di distribuzione di messaggi tra i servizi. Garantire ad esempio che il messaggio arrivi ad uno e un solo servizio.
  • Locks, ovvero gestire l’accesso ad una risorsa limitata. Bloccare con un “lucchetto” la risorsa affinché un servizio alla volta possa accedervi, e rilasciarla al termine delle operazioni o comunque in caso di malfunzionamento del servizio stesso, per evitare di bloccare tutto il sistema.
  • Two-phased Commit: in caso di transazione che coinvolge più servizi, assicurarsi che ognuno completi la transazione (“committi”) oppure che ogni servizio possa fare “rollback” ovvero tornare indietro ad una situazione di partenza pulita.
  • Leader Election: il problema iniziale.

Perché non usare ZooKeeper?

Apache ZooKeeper – caratteristiche principali

Struttura gerarchica

Ogni client che si connette a ZooKeeper ha la visione di un namespace gerarchico. Ogni nodo, o meglio znode per usare la terminologia di ZooKeeper, può essere sia directory, quindi avere altri nodi, oppure file ovvero contenere dati.

API semplici

ZooKeeper ha poche ma semplici API:

  • create: creare un nodo in una certa directory dell’albero. Due modalità di creazione:
    • Sequence Node: il nodo viene creato come sequenziale ovvero ZooKeeper al nome aggiunge un numero come suffisso, così da gestire il caso di inserimento di tanti nodi da parte di tanti client.
    • Ephemeral Node: ogni nodo creato con questo flag attivo verrà eliminato da ZooKeeper non appena il client che lo ha creato termina la sessione (per qualunque motivo, anche in caso di problemi di connettività del client).
  • delete: eliminare un nodo.
  • exists: verificare l’esistenza di un nodo.
  • getData: farsi restituire i dati del nodo.
  • setData: inserire dei dati nel nodo.
  • getChildren: chiedere la lista dei nodi figli.

Ogni volta che si effettua una richiesta per un nodo (getChildren ad esempio) è possibile sottoscriversi a quel nodo, ovvero diventare “watcher” ed essere avvisati per ogni modifica relativa a quello specifico nodo.

Gestione dei problemi con Apache ZooKeeper

Leader Election

Con l’API a disposizione è relativamente semplice gestire il problema, è possibile infatti permettere che ogni servizio (client) crei i nodi in maniera effimera e sequenziale. La sequenzialità stabilisce chi sia il nodo leader, inoltre attraverso il getChildren e il sistema di notifiche (“watch”) ogni client sarà sempre aggiornato sullo stato attuale di tutti i nodi dei sistema.

Lock

In maniera molto simile si possono gestire i lock su una risorsa. Una volta identificato il nodo lock sulla risorsa, i client interessati creano dei nodi effimeri e sequenziali. Non appena il servizio rilascerà la risorsa o terminerà la sessione cancellando il nodo, proprio perché effimero, il primo della lista degli altri nodi potrà accedere alla risorsa.

Two-phased Commit

Ancora una volta, potremmo pensare ad un’organizzazione simile. Potremmo avere un responsabile dell’inizio della transazione, quindi un coordinatore che crea il nodo transaction e che invia il comando ad ogni servizio coinvolto nell’operazione. Ogni servizio dovrà creare un sotto-nodo e nei dati scrivere l’esito della fase (“commit” o “abort”). In questa maniera il coordinatore avrà sempre la situazione aggiornata e magari interrompere la transazione non appena verrà notificato di un errore da parte di un altro nodo.

Considerazioni su Apache ZooKeeper

Con i tre esempi che abbiamo appena visto salta all’occhio una prima considerazione su ZooKeeper, ovvero che le sue API sono tanto semplici quanto versatili (nel sito di ZooKeeper in effetti si parla di ricette).

Ma non è tutto così semplice.

Innanzitutto ZooKeeper non deve essere pensato come esistente su un singolo nodo bensì su più nodi, con ovvii problemi di gestione della replicabilità e sincronizzazione del dato. Eleggere un leader è un problema molto più complesso se calato in un contesto di sistema distribuito.

Bisogna inoltre prestare attenzione anche in altre situazioni:

  • In fase di deploy di un sistema con ZooKeeper, cercando di avere un numero di znode dispari proprio per evitare problemi di pareggio per leader election o lock di risorse.
  • Nel caso in cui parte della rete viene isolata, e quindi znode isolati, bisogna evitare che nelle parti isolate vengano eletti due leader distinti che quindi creerebbero delle situazioni di inconsistenza non appena tutta la rete torna disponibile.

Agli occhi di ogni sviluppatore però, questa complessità viene mascherata viene mascherata proprio attraverso queste API.

Articolo scritto da