Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Zookeeper API


May 26, 2021 Zookeeper


Table of contents


ZooKeeper has an official API that binds Java and C. T he Zookeeper community provides unofficial APIs for most languages (.NET, python, etc.). /b10> Using the ZooKeeper API, applications can connect, interact, manipulate data, coordinate, and finally disconnect from the ZooKeeper collection.

The ZooKeeper API has a wealth of features to get all the features of the ZooKeeper collection in a simple and secure way. /b10> The ZooKeeper API provides synchronization and asynchronous methods.

The ZooKeeper collection and the ZooKeeper API complement each other in every way and are of great help to developers. /b10> Let's discuss Java binding in this chapter.

The basics of the ZooKeeper API

Applications that interact with the ZooKeeper collection are called ZooKeeper clients, or clients for short.

Znode is the core component of the ZooKeeper collection, and the ZooKeeper API provides a small group of methods to manipulate all the details of znode using the ZooKeeper collection.

Clients should follow the steps to interact clearly and cleanly with the ZooKeeper collection.

  • Connect to the ZooKeeper collection. /b10> The ZooKeeper collection assigns a session ID to the client.

  • Send a heartbeat to the server on a regular basis. /b10> Otherwise, the ZooKeeper collection expires the session ID and the client needs to reconnect.

  • You can get/set znode as long as the session ID is active.

  • When all tasks are complete, disconnect from the ZooKeeper collection. /b10> If the client is in activity for a long time, the ZooKeeper collection automatically disconnects the client.

Java binding

Let's take a look at the most important set of ZooKeeper APIs in this chapter. /b10> The core part of the ZooKeeper API is the ZooKeeper class. It provides the option to connect the ZooKeeper collection in its constructor and has the following methods:

  • Connect - Connect to the ZooKeeper collection

  • Create - Create znode

  • exists - Check whether znode exists and its information

  • getData - Get data from a specific znode

  • setData - Set the data in a specific znode

  • getChildren - Gets all the child nodes in a particular znode

  • delete - Delete a specific znode and all its children

  • close - Close the connection

Connect to the ZooKeeper collection

The ZooKeeper class provides connect functionality through its constructors. The constructor's signature is as follows:

ZooKeeper(String connectionString, int sessionTimeout, Watcher watcher)
  • ConnectionString - ZooKeeper Collection Host.

  • sessionTimeout - Session timed out in milliseconds.

  • Watcher - The object that implements the Monitor interface. The ZooKeeper collection returns the connection state through the monitor object.

Let's create a new help class zooKeeperConnection and add a method connect. /b10> The connect method creates a ZooKeeper object, connects to the ZooKeeper collection, and then returns the object.

Here CountDownLatch is used to stop (wait) the main process until the client is connected to the ZooKeeper collection.

The ZooKeeper collection replies to the connection state with a monitor callback. Once the client is connected to the ZooKeeper collection, the monitor callback is called, and the monitor callback function calls countDownLatch's countDown method to release the lock in the main process await.

The following is the full code for the connection to the ZooKeeper collection.

Code: ZooKeeperConnection .java

// import java classes
import java.io.IOException;
import java.util.concurrent.CountDownLatch;

// import zookeeper classes
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.AsyncCallback.StatCallback;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.data.Stat;

public class ZooKeeperConnection {

   // declare zookeeper instance to access ZooKeeper ensemble
   private ZooKeeper zoo;
   final CountDownLatch connectedSignal = new CountDownLatch(1);

   // Method to connect zookeeper ensemble.
   public ZooKeeper connect(String host) throws IOException,InterruptedException {
	
      zoo = new ZooKeeper(host,5000,new Watcher() {
		
         public void process(WatchedEvent we) {

            if (we.getState() == KeeperState.SyncConnected) {
               connectedSignal.countDown();
            }
         }
      });
		
      connectedSignal.await();
      return zoo;
   }

   // Method to disconnect from zookeeper server
   public void close() throws InterruptedException {
      zoo.close();
   }
}

Save the code above, which will be used in the next section to connect to the ZooKeeper collection.

Create Znode

The ZooKeeper class provides a create method for creating a new znode in the ZooKeeper collection. ture of the create method is as follows:

create(String path, byte[] data, List<ACL> acl, CreateMode createMode)
  • Path - Znode path. For example, / / myapp1, / myapp2, / myapp1 / mydata1, myapp2 / mydata1 / myanothersubdata

  • data - The data to store in the specified znode path

  • acl - A list of access controls for the nodes to be created. /b10> The ZooKeeper API provides a static interface, ZooDefs.Ids, to get some basic acl lists. /b11> For example, ZooDefs.Ids.OPEN_ACL_UNSAFE returns the list of acls that open znode.

  • CreateMode - The type of node, i.e. temporary, sequential, or both. /b10> This is an enumerity.

Let's create a new Java application to check the create capabilities of the ZooKeeper API. /b10> Create a file ZKCreate .java. /b11> In the main method, create an object of the type ZooKeeperConnection and call the connect method to connect to the ZooKeeper collection.

The connect method returns the ZooKeeper object zk. /b10> Now call the create method of the zk object using custom path and data.

The complete program code for creating znode is as follows:

Code: ZKCreate .java

import java.io.IOException;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;

public class ZKCreate {
   // create static instance for zookeeper class.
   private static ZooKeeper zk;

   // create static instance for ZooKeeperConnection class.
   private static ZooKeeperConnection conn;

   // Method to create znode in zookeeper ensemble
   public static void create(String path, byte[] data) throws 
      KeeperException,InterruptedException {
      zk.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE,
      CreateMode.PERSISTENT);
   }

   public static void main(String[] args) {

      // znode path
      String path = "/MyFirstZnode"; // Assign path to znode

      // data in byte array
      byte[] data = "My first zookeeper app".getBytes(); // Declare data
		
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("localhost");
         create(path, data); // Create the data to the specified path
         conn.close();
      } catch (Exception e) {
         System.out.println(e.getMessage()); //Catch error message
      }
   }
}

Once the application is compiled and executed, znode with the specified data is created in the ZooKeeper collection. Y ou can use the ZooKeeper CLI zkCli.sh to check.

cd /path/to/zookeeper
bin/zkCli.sh
>>> get /MyFirstZnode

Exists - Check the presence of Znode

The ZooKeeper class provides an exists method to check the presence of znode. I f the specified znode exists, a znode metadata is returned. ists method is as follows:

exists(String path, boolean watcher)
  • Path - Znode path

  • Watcher - Boolean value, which specifies whether to monitor the specified znode

Let's create a new Java application to check the "exists" functionality of the ZooKeeper API. /b10> Create the file "ZKExists .java." /b11> In the main method, create the ZooKeeper object "zk" using the ZooKeeper Connect object. /b12> Then, use the custom "path" to call the "exists" method of the "zk" object. The full list is as follows:

Code: ZKExists .java

import java.io.IOException;

import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.data.Stat;

public class ZKExists {
   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;

   // Method to check existence of znode and its status, if znode is available.
   public static Stat znode_exists(String path) throws
      KeeperException,InterruptedException {
      return zk.exists(path, true);
   }

   public static void main(String[] args) throws InterruptedException,KeeperException {
      String path = "/MyFirstZnode"; // Assign znode to the specified path
			
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("localhost");
         Stat stat = znode_exists(path); // Stat checks the path of the znode
				
         if(stat != null) {
            System.out.println("Node exists and the node version is " +
            stat.getVersion());
         } else {
            System.out.println("Node does not exists");
         }
				
      } catch(Exception e) {
         System.out.println(e.getMessage()); // Catches error messages
      }
   }
}

Once the application is compiled and executed, you will get the following output.

Node exists and the node version is 1.

GetData method

The ZooKeeper class provides the getData method to get the data attached to the specified znode and its status. The getData method is signed as follows:

getData(String path, Watcher watcher, Stat stat)
  • Path - Znode path.

  • Watcher - a callback function of the monitor type. /b10> When the specified znode data changes, the ZooKeeper collection is notified by a monitor callback. /b11> This is a one-time notification.

  • stat - returns the metadata for znode.

Let's create a new Java application to learn about the getData functionality of the ZooKeeper API. /b10> Create a file ZKGetData .java. /b11> In the main method, create a ZooKeeper object zk using the ZooKeeperConnection object. /b12> Then, use a custom path to call the getData method of the zk object.

Here's the full program code for getting data from the specified node:

Code: ZKGetData .java

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.data.Stat;

public class ZKGetData {

   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;
   public static Stat znode_exists(String path) throws 
      KeeperException,InterruptedException {
      return zk.exists(path,true);
   }

   public static void main(String[] args) throws InterruptedException, KeeperException {
      String path = "/MyFirstZnode";
      final CountDownLatch connectedSignal = new CountDownLatch(1);
		
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("localhost");
         Stat stat = znode_exists(path);
			
         if(stat != null) {
            byte[] b = zk.getData(path, new Watcher() {
				
               public void process(WatchedEvent we) {
					
                  if (we.getType() == Event.EventType.None) {
                     switch(we.getState()) {
                        case Expired:
                        connectedSignal.countDown();
                        break;
                     }
							
                  } else {
                     String path = "/MyFirstZnode";
							
                     try {
                        byte[] bn = zk.getData(path,
                        false, null);
                        String data = new String(bn,
                        "UTF-8");
                        System.out.println(data);
                        connectedSignal.countDown();
							
                     } catch(Exception ex) {
                        System.out.println(ex.getMessage());
                     }
                  }
               }
            }, null);
				
            String data = new String(b, "UTF-8");
            System.out.println(data);
            connectedSignal.await();
				
         } else {
            System.out.println("Node does not exists");
         }
      } catch(Exception e) {
        System.out.println(e.getMessage());
      }
   }
}

Once the application is compiled and executed, you will get the following output

My first zookeeper app

The application will wait for further notification from the ZooKeeper collection. /b10> Use the ZooKeeper CLI zkCli.sh the data that specifies znode.

cd /path/to/zookeeper
bin/zkCli.sh
>>> set /MyFirstZnode Hello

The application will now print the following output and exit.

Hello

SetData method

The ZooKeeper class provides a setData method to modify the data attached in the specified znode. The setData method is signed as follows:

setData(String path, byte[] data, int version)
  • Path - Znode path

  • data - The data to store in the specified znode path.

  • version - the current version of znode. /b10> ZooKeeper updates znode's version number whenever the data changes.

Now let's create a new Java application to learn about the setData functionality of the ZooKeeper API. /b10> Create a file ZKSetData .java. /b11> In the main method, create a ZooKeeper object zk using the ZooKeeperConnection object. /b12> Then, the setData method of the zk object is called with the specified path, new data, and node version.

The following is the complete program code for modifying the data attached to the specified znode.

Code: ZKSetData .java

import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;

import java.io.IOException;

public class ZKSetData {
   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;

   // Method to update the data in a znode. Similar to getData but without watcher.
   public static void update(String path, byte[] data) throws
      KeeperException,InterruptedException {
      zk.setData(path, data, zk.exists(path,true).getVersion());
   }

   public static void main(String[] args) throws InterruptedException,KeeperException {
      String path= "/MyFirstZnode";
      byte[] data = "Success".getBytes(); //Assign data which is to be updated.
		
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("localhost");
         update(path, data); // Update znode data to the specified path
      } catch(Exception e) {
         System.out.println(e.getMessage());
      }
   }
}

After the application is compiled and executed, the specified znode data is changed and can be checked using zkCli.sh zooKeeper CLI.

cd /path/to/zookeeper
bin/zkCli.sh
>>> get /MyFirstZnode

GetChildren method

The ZooKeeper class provides the getChildren method to get all the child nodes of a particular znode. The getChildren method is signed as follows:

getChildren(String path, Watcher watcher)
  • Path - Znode path.

  • Watcher - a callback function of the monitor type. /b10> The ZooKeeper collection is notified when the specified znode is deleted or when the child nodes under znode are created/deleted. /b11> This is a one-time notification.

Code: ZKGetChildren.java

import java.io.IOException;
import java.util.*;

import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.data.Stat;

public class ZKGetChildren {
   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;

   // Method to check existence of znode and its status, if znode is available.
   public static Stat znode_exists(String path) throws 
      KeeperException,InterruptedException {
      return zk.exists(path,true);
   }

   public static void main(String[] args) throws InterruptedException,KeeperException {
      String path = "/MyFirstZnode"; // Assign path to the znode
		
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("localhost");
         Stat stat = znode_exists(path); // Stat checks the path

         if(stat!= null) {

            //“getChildren" method- get all the children of znode.It has two
            args, path and watch
            List <String> children = zk.getChildren(path, false);
            for(int i = 0; i < children.size(); i++)
            System.out.println(children.get(i)); //Print children's
         } else {
            System.out.println("Node does not exists");
         }

      } catch(Exception e) {
         System.out.println(e.getMessage());
      }

   }

}

Before we run the program, let's use the ZooKeeper CLI zkCli.sh to create two child nodes for /MyFirstZnode.

cd /path/to/zookeeper
bin/zkCli.sh
>>> create /MyFirstZnode/myfirstsubnode Hi
>>> create /MyFirstZnode/mysecondsubmode Hi

The compiler and run program will now output the znode created above.

myfirstsubnode
mysecondsubnode

Delete Znode

The ZooKeeper class provides a delete method to remove the specified znode. The signature of the delete method is as follows:

delete(String path, int version)
  • Path - Znode path.

  • version - the current version of znode.

Let's create a new Java application to learn about the delete functionality of the ZooKeeper API. C reate a file ZKDelete .java. I n the main method, create a ZooKeeper object zk using the ZooKeeperConnection object. Then, the delete method of the zk object is called with the specified path and version number.

The complete program code for removing znode is as follows:

Code: ZKDelete .java

import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException;

public class ZKDelete {
   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;

   // Method to check existence of znode and its status, if znode is available.
   public static void delete(String path) throws KeeperException,InterruptedException {
      zk.delete(path,zk.exists(path,true).getVersion());
   }

   public static void main(String[] args) throws InterruptedException,KeeperException {
      String path = "/MyFirstZnode"; //Assign path to the znode
		
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("localhost");
         delete(path); //delete the node with the specified path
      } catch(Exception e) {
         System.out.println(e.getMessage()); // catches error messages
      }
   }
}