Erste Schritte mit Java und Zookeeper

Erste Schritte mit Java und Zookeeper

1. Überblick

Apache ZooKeeperis a distributed coordination service erleichtert die Entwicklung verteilter Anwendungen. Es wird von Projekten wie Apache Hadoop, HBase undothersfür verschiedene Anwendungsfälle wie Leader-Wahl, Konfigurationsmanagement, Knotenkoordination, Server-Lease-Management usw. verwendet.

Nodes within ZooKeeper cluster store their data in a shared hierarchal namespace ähnelt einem Standarddateisystem oder einer Baumdatenstruktur.

In diesem Artikel erfahren Sie, wie Sie die Java-API von Apache Zookeeper zum Speichern, Aktualisieren und Löschen von in ZooKeeper gespeicherten Informationen verwenden.

2. Setup

Die neueste Version der Apache ZooKeeper Java-Bibliothek finden Sie unterhere:


    org.apache.zookeeper
    zookeeper
    3.4.11

3. ZooKeeper-Datenmodell - ZNode

ZooKeeper hat einen hierarchischen Namespace, ähnlich wie ein verteiltes Dateisystem, in dem Koordinationsdaten wie Statusinformationen, Koordinationsinformationen, Standortinformationen usw. gespeichert werden. Diese Informationen werden auf verschiedenen Knoten gespeichert.

Jeder Knoten in einem ZooKeeper-Baum wird als ZNode bezeichnet.

Jeder ZNode verwaltet Versionsnummern und Zeitstempel für Daten- oder ACL-Änderungen. Auf diese Weise kann ZooKeeper auch den Cache validieren und Aktualisierungen koordinieren.

4. Installation

4.1. Installation

Die neueste Version von ZooKeeper kann vonhere heruntergeladen werden. Bevor wir dies tun, müssen wir sicherstellen, dass wir die beschriebenen Systemanforderungenhere erfüllen.

4.2. Standalone-Modus

In diesem Artikel wird ZooKeeper in einem eigenständigen Modus ausgeführt, da nur eine minimale Konfiguration erforderlich ist. Befolgen Sie die in der Dokumentationhere beschriebenen Schritte.

Hinweis: Im Standalone-Modus findet keine Replikation statt. Wenn der ZooKeeper-Prozess fehlschlägt, fällt der Dienst aus.

5. ZooKeeper CLI-Beispiele

Wir verwenden jetzt die ZooKeeper-Befehlszeilenschnittstelle (CLI), um mit ZooKeeper zu interagieren:

bin/zkCli.sh -server 127.0.0.1:2181

Über dem Befehl wird lokal eine eigenständige Instanz gestartet. Schauen wir uns nun an, wie Sie einen ZNode erstellen und Informationen in ZooKeeper speichern:

[zk: localhost:2181(CONNECTED) 0] create /MyFirstZNode ZNodeVal
Created /FirstZnode

Wir haben gerade einen ZNode‘MyFirstZNode’ im Stammverzeichnis des hierarchischen ZooKeeper-Namespace erstellt und‘ZNodeVal’ darauf geschrieben.

Da wir kein Flag übergeben haben, bleibt ein erstellter ZNode bestehen.

Lassen Sie uns jetzt einen‘get'-Befehl ausgeben, um die Daten sowie die mit einem ZNode verknüpften Metadaten abzurufen:

[zk: localhost:2181(CONNECTED) 1] get /FirstZnode

“Myfirstzookeeper-app”
cZxid = 0x7f
ctime = Sun Feb 18 16:15:47 IST 2018
mZxid = 0x7f
mtime = Sun Feb 18 16:15:47 IST 2018
pZxid = 0x7f
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 22
numChildren = 0

Wir können die Daten eines vorhandenenZNode mit der Operationset aktualisieren.

Zum Beispiel:

set /MyFirstZNode ZNodeValUpdated

Dadurch werden die Daten beiMyFirstZNode vonZNodeVal aufZNodeValUpdated. aktualisiert

6. ZooKeeper Java API Beispiel

Schauen wir uns nun die Zookeeper Java API an und erstellen einen Knoten, aktualisieren den Knoten und rufen einige Daten ab.

6.1. Java-Pakete

Die ZooKeeper Java-Bindungen bestehen hauptsächlich aus zwei Java-Paketen:

  1. org.apache.zookeeper:, das die Hauptklasse der ZooKeeper-Clientbibliothek zusammen mit vielen statischen Definitionen der ZooKeeper-Ereignistypen und -Zustände definiert

  2. org.apache.zookeeper.data: Definiert die mit ZNodes verknüpften Merkmale wie Zugriffssteuerungslisten (ACL), IDs, Statistiken usw.

Es gibt auch ZooKeeper Java-APIs, die in der Serverimplementierung verwendet werden, z. B.org.apache.zookeeper.server,org.apache.zookeeper.server.quorum undorg.apache.zookeeper.server.upgrade.

Sie gehen jedoch über den Rahmen dieses Artikels hinaus.

6.2. Herstellen einer Verbindung zu einer ZooKeeper-Instanz

Erstellen wir nun die KlasseZKConnection, mit der eine Verbindung zu einem bereits laufenden ZooKeeper hergestellt und von dieser getrennt wird:

public class ZKConnection {
    private ZooKeeper zoo;
    CountDownLatch connectionLatch = new CountDownLatch(1);

    // ...

    public ZooKeeper connect(String host)
      throws IOException,
      InterruptedException {
        zoo = new ZooKeeper(host, 2000, new Watcher() {
            public void process(WatchedEvent we) {
                if (we.getState() == KeeperState.SyncConnected) {
                    connectionLatch.countDown();
                }
            }
        });

        connectionLatch.await();
        return zoo;
    }

    public void close() throws InterruptedException {
        zoo.close();
    }
}

Um einen ZooKeeper-Dienst zu verwenden, muss eine Anwendung zuerst ein Objekt vonZooKeeper class, which is the main class of ZooKeeper client library instanziieren.

In der Methodeconnectinstanziieren wir eine Instanz der KlasseZooKeeper. Außerdem haben wir eine Rückrufmethode registriert, um dieWatchedEvent von ZooKeeper für die Verbindungsannahme zu verarbeiten und dieconnect-Methode entsprechend mit dercountdown-Methode vonCountDownLatch zu beenden.

Sobald eine Verbindung zu einem Server hergestellt ist, wird dem Client eine Sitzungs-ID zugewiesen. Damit die Sitzung gültig bleibt, sollte der Client regelmäßig Heartbeats an den Server senden.

Die Client-Anwendung kann ZooKeeper-APIs aufrufen, solange ihre Sitzungs-ID gültig bleibt.

6.3. Client-Operationen

Wir erstellen jetzt eineZKManager-Schnittstelle, die verschiedene Vorgänge wie das Erstellen eines ZNode und das Speichern einiger Daten sowie das Abrufen und Aktualisieren der ZNode-Daten verfügbar macht:

public interface ZKManager {
    public void create(String path, byte[] data)
      throws KeeperException, InterruptedException;
    public Object getZNodeData(String path, boolean watchFlag);
    public void update(String path, byte[] data)
      throws KeeperException, InterruptedException;
}

Schauen wir uns nun die Implementierung der obigen Schnittstelle an:

public class ZKManagerImpl implements ZKManager {
    private static ZooKeeper zkeeper;
    private static ZKConnection zkConnection;

    public ZKManagerImpl() {
        initialize();
    }

    private void initialize() {
        zkConnection = new ZKConnection();
        zkeeper = zkConnection.connect("localhost");
    }

    public void closeConnection() {
        zkConnection.close();
    }

    public void create(String path, byte[] data)
      throws KeeperException,
      InterruptedException {

        zkeeper.create(
          path,
          data,
          ZooDefs.Ids.OPEN_ACL_UNSAFE,
          CreateMode.PERSISTENT);
    }

    public Object getZNodeData(String path, boolean watchFlag)
      throws KeeperException,
      InterruptedException {

        byte[] b = null;
        b = zkeeper.getData(path, null, null);
        return new String(b, "UTF-8");
    }

    public void update(String path, byte[] data) throws KeeperException,
      InterruptedException {
        int version = zkeeper.exists(path, true).getVersion();
        zkeeper.setData(path, data, version);
    }
}

Im obigen Code werdenconnect- unddisconnect-Aufrufe an die zuvor erstellteZKConnection-Klasse delegiert. Unserecreate-Methode wird verwendet, um einen ZNode an einem bestimmten Pfad aus den Byte-Array-Daten zu erstellen. Nur zu Demonstrationszwecken haben wir ACL vollständig geöffnet.

Nach der Erstellung ist der ZNode dauerhaft und wird nicht gelöscht, wenn der Client die Verbindung trennt.

Die Logik zum Abrufen von ZNode-Daten von ZooKeeper in unserergetZNodeData-Methode ist recht einfach. Schließlich überprüfen wir mit derupdate-Methode das Vorhandensein von ZNode auf dem angegebenen Pfad und rufen es ab, falls vorhanden.

Darüber hinaus überprüfen wir zum Aktualisieren der Daten zunächst die Existenz von ZNode und erhalten die aktuelle Version. Dann rufen wir diesetData-Methode mit dem Pfad von ZNode, Daten und der aktuellen Version als Parameter auf. ZooKeeper aktualisiert die Daten nur, wenn die übergebene Version mit der neuesten Version übereinstimmt.

7. Fazit

Bei der Entwicklung verteilter Anwendungen spielt Apache ZooKeeper eine wichtige Rolle als verteilter Koordinierungsdienst. Speziell für Anwendungsfälle wie das Speichern einer gemeinsam genutzten Konfiguration, die Wahl des Masterknotens usw.

ZooKeeper bietet auch eine elegante Java-basierte API, die im clientseitigen Anwendungscode für die nahtlose Kommunikation mit ZooKeeper ZNodes verwendet werden kann.

Und wie immer finden Sie alle Quellen für dieses Tutorial inover on Github.