Connect to ZooKeeper via API

ZooKeeper provides official API with Java and C bindings. APIs for some of the other languages are provided by the ZooKeeper community.

The ZooKeeper API enables applications to connect to a server, execute commands, manipulate data, and coordinate tasks.

ZooKeeper client

An application that interacts with a ZooKeeper server is called a ZooKeeper client.

The prefered algorithm for client interaction with the ZooKeeper server looks like this:

  1. Create a connection to the server. The server will assign a session ID for the client.

  2. Send heartbeats to the server. Otherwise, the session ID expires and the client will have to reconnect.

  3. Perform the necessary operations, for example, get or set the znodes.

  4. Disconnect from the server. If the client is inactive for a prolonged time, the server will automatically disconnect the client.

To learn more about developing for Zookeeper, read the ZooKeeper Programmer’s Guide.

Java

To connect to a ZooKeeper server using the Java API, you need to set up an environment and install the dependencies. The example code below creates a connection to the ZooKeeper server, outputs confirmation upon successful connection, and returns an error message if it was unable to connect.

The developer tools used in the process are Vi text editor, virtual machine with CentOS 7, and Maven compiler. A different setup will require calibration.

  1. Install Maven.

  2. Write a connector class:

    package my.example.zookeeper;
    
    import java.io.IOException;
    import java.util.concurrent.CountDownLatch;
    
    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 {
    
       private ZooKeeper zoo;
       final CountDownLatch connectedSignal = new CountDownLatch(1);
    
       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;
       }
    
       public void close() throws InterruptedException {
          zoo.close();
       }
    }
  3. Create a pom.xml file for building the project with Maven.

    Sample pom.xml file
    <project>
            <modelVersion>4.0.0</modelVersion>
            <groupId>my.example.zookeeper</groupId>
            <artifactId>zoo-connect</artifactId>
            <version>0.1.0-SNAPSHOT</version>
            <packaging>jar</packaging>
      <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
      </properties>
      <dependencies>
            <dependency>
                <groupId>org.apache.hadoop</groupId>
                <artifactId>hadoop-hdfs</artifactId>
                <version>2.7.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.11</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.hadoop</groupId>
                <artifactId>hadoop-common</artifactId>
                <version>2.7.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.hadoop</groupId>
                <artifactId>hadoop-core</artifactId>
                <version>1.2.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.hadoop</groupId>
                <artifactId>hadoop-client</artifactId>
                <version>2.7.1</version>
            </dependency>
      </dependencies>
    <build>
        <plugins>
          <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                  <archive>
                    <manifest>
                      <addClasspath>true</addClasspath>
                      <mainClass>my.example.zookeeper.Main</mainClass>
                    </manifest>
                  </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>assemble-all</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
          <plugin>
            <!-- Build an executable JAR -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
              <archive>
                <manifest>
                  <addClasspath>true</addClasspath>
                  <mainClass>my.example.zookeeper.Main</mainClass>
                </manifest>
                 <addClasspath>true</addClasspath>
                  <mainClass>my.example.zookeeper.Main</mainClass>
                </manifest>
              </archive>
            </configuration>
          </plugin>
        </plugins>
      </build>
    
    </project>
  4. Build the project:

    $ mvn package
  5. Run the created Java class:

    $ java -jar <java-class>.jar

    Where <java-class> is the name of your Java connector program.

The output will include information about successful connection:

23/12/14 19:43:34 INFO zookeeper.ZooKeeper: Initiating client connection, connectString=127.0.0.1 sessionTimeout=2181 watcher=my.example.zookeeper.Main$MyWatcher@433c675d
23/12/14 19:43:34 INFO zookeeper.ClientCnxn: Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
23/12/14 19:43:34 INFO zookeeper.ClientCnxn: Socket connection established to 127.0.0.1/127.0.0.1:2181, initiating session
23/12/14 19:43:34 INFO zookeeper.ClientCnxn: Session establishment complete on server 127.0.0.1/127.0.0.1:2181, sessionid = 0x1000000cebe0004, negotiated timeout = 4000
23/12/14 19:43:34 INFO zookeeper.ZooKeeper: Session: 0x1000000cebe0004 closed

C

To connect to a ZooKeeper server using the C API, you need to set up an environment and install the dependencies. The example code below creates a connection to the ZooKeeper server, outputs confirmation upon successful connection, and returns an error message if it was unable to connect.

The developer tools used in the process are Vi text editor, virtual machine with Ubuntu 23.10, and GCC compiler. A different setup will require calibration.

Another example of a C client is available in the Apache ZooKeeper repository.

Before building a ZooKeeper client in C, download the zookeeper.h library or build it yourself using the ant build tool. If you are building a multithreaded client, compile with -DTHREADED compiler flag to enable the multi-threaded version of the library, and then link against the zookeeper_mt library. If you are building a single-threaded client, do not compile with -DTHREADED, and link against the zookeeper_st library.

To create a sample ZooKeeper client in C:

  1. Write a connector program:

    #include <stdio.h>
    #include <stdlib.h>
    #include <zookeeper/zookeeper.h>
    #include <errno.h>
    
    static int completed = 0;
    
    void watcher(zhandle_t *zkH, int type, int state, const char *path, void *watcherCtx) {
        if (type == ZOO_SESSION_EVENT) {
            if (state == ZOO_CONNECTED_STATE) {
            } else if (state == ZOO_NOTCONNECTED_STATE ) {
            } else if (state == ZOO_EXPIRED_SESSION_STATE) {
                completed = 1;
                zookeeper_close(zkH);
            }
        }
    }
    
    void aget_strings_completion(int rc, const struct String_vector *strings, const void *data) {
        int i;
        if (strings) {
            for (i=0; i < strings->count; i++) {
                printf("\t%s\n", strings->data[i]);
            }
        }
        completed = 1;
    }
    
    int main(int argc, char *argv[]) {
        zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
        zhandle_t *handler = zookeeper_init("127.0.0.1:2181", watcher, 30000, NULL, NULL, 0);
        if (!handler) {
            return EXIT_FAILURE;
        }
        int rc = zoo_aget_children(handler, "/", 1, aget_strings_completion, NULL);
        if (rc) {
            fprintf(stderr, "Error %d\n", rc);
            return EXIT_FAILURE;
        }
        while (!completed) {
        }
        zookeeper_close(handler);
        return EXIT_SUCCESS;
    }
  2. Compile the code. For example, using the following command:

    $ gcc main.c -o <program-name> -lzookeeper_mt

    Where <program-name> is the name of your program.

With the client console output configured, you can see the following:

2023-12-18 12:23:11,953:6904(0x7fa0e9d146c0):ZOO_INFO@check_events@2992: initiated connection to server 127.0.0.1:2181
2023-12-18 12:23:11,965:6904(0x7fa0e9d146c0):ZOO_INFO@finalize_session_establishment@2866: session establishment complete on server 127.0.0.1:2181, sessionId=0x1000000cebe0005, negotiated timeout=30000
2023-12-18 12:23:11,965:6904(0x7fa0e9d146c0):ZOO_DEBUG@finalize_session_establishment@2876: Calling a watcher for a ZOO_SESSION_EVENT and the state=ZOO_CONNECTED_STATE
2023-12-18 12:23:11,965:6904(0x7fa0e95136c0):ZOO_DEBUG@process_completions@3341: Calling a watcher for node [], type = -1 event=ZOO_SESSION_EVENT
2023-12-18 12:23:11,966:6904(0x7fa0e9d146c0):ZOO_DEBUG@zookeeper_process@3503: Queueing asynchronous response
2023-12-18 12:23:11,966:6904(0x7fa0e95136c0):ZOO_DEBUG@deserialize_response@3233: Calling COMPLETION_STRINGLIST for xid=0x658039b0 failed=0 rc=0
        zookeeper
        arenadata
        hadoop-ha
2023-12-18 12:23:11,966:6904(0x7fa0e95136c0):ZOO_DEBUG@do_completion@483: completion thread terminated
2023-12-18 12:23:11,966:6904(0x7fa0e9d146c0):ZOO_DEBUG@do_io@460: IO thread terminated
2023-12-18 12:23:11,966:6904(0x1a373c0):ZOO_INFO@zookeeper_close@3854: Closing zookeeper sessionId=0x1000000cebe0005 to 127.0.0.1:2181
Found a mistake? Seleсt text and press Ctrl+Enter to report it