API usage of zookeeper

Time:2020-3-5

POM configuration

Import zookeeper and JUnit

<dependencies>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.5.6</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

Create session

Before, for creating a session, this part of code will not be pasted later

private static ZooKeeper zooKeeper;
private static Stat stat = new Stat();

@Before
public void before() {
    zooKeeper = ZookeeperConnect.getZookeeper();
}

For the knowledge points of countdownlatch, refer to countdownlatch learned from Java Concurrent Programming. The zookeeperzookeeperconnect code is as follows:

public class ZookeeperConnect {
    private static final String CONNECT_STRING = "172.17.0.2:2181,172.17.0.3:2181,172.17.0.4:2181";
    public static CountDownLatch countDownLatch = new CountDownLatch(1);
    static ZooKeeper zooKeeper = null;

    public static ZooKeeper getZookeeper() {
        try {
            //The first parameter is the address of each node in the zookeeper cluster. Multiple addresses are separated by commas
            //The second parameter, session timeout, in milliseconds.
            //The third parameter is watcher. Only after the connection is successfully controlled by countdownlatch, can zookeeper be returned.
            zooKeeper = new ZooKeeper(CONNECT_STRING, 5000, new Watcher() {
                public void process(WatchedEvent watchedEvent) {
                    System.out.println("watchedEvent:" + watchedEvent);
                    if (Event.KeeperState.SyncConnected == watchedEvent.getState()) {
                        if (Event.EventType.None == watchedEvent.getType() && null == watchedEvent.getPath()) {
                            countDownLatch.countDown();
                        }
                    }
                }
            });
            System. Out. Println ("waiting");
            countDownLatch.await();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System. Out. Println ("get to connection");
        return zooKeeper;
    }
}

Test code

@Test
public void testConnect(){

}

Operation result:
API usage of zookeeper

Additions and deletions

Create node

Includes synchronous and asynchronous. The test code is as follows:

@Test
public void testCreate() throws KeeperException, InterruptedException {
    //The first parameter is the node path, which cannot be set directly and multi-level, and an error of keepererrorcode = nonode for will be reported
    //The second parameter is the content of the node
    //The third parameter is the ACL policy of the node. First, use open ACL unsafe to relax the permission operation
    //The fourth parameter is the type of node, such as persistent node, persistent ordered node, temporary node and temporary ordered node
    String result = zooKeeper.create("/node", "node".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    System. Out. Println ("new node succeeded:" + result);
}

@Test
public void testCreateASync() {
    //The fifth parameter is used for asynchronous callback
    //The sixth parameter is to pass a context information when it is used for callback
    zooKeeper.create("/nodeASync", "nodeASync".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
            CreateMode.PERSISTENT, new MyStringCallBack(), "testCreateASync");
    System. Out. Println ("new node succeeded");
    try {
        TimeUnit.SECONDS.sleep(3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

MyStringCallBack

public class MyStringCallBack implements AsyncCallback.StringCallback {
    public void processResult(int rc, String path, Object ctx, String name) {
        System.out.println("rc:" + rc + ",path:" + path + ",ctx:" + ctx + "name," + name);
    }
}

The synchronous operation results are as follows:
API usage of zookeeper
The asynchronous operation results are as follows:
API usage of zookeeper
In the example above, you can see that,testCreate()Exceptions are thrown, while asynchronous exceptions are not thrown. The exception information is responded by result code.
The interface of callback function is inheritedAsyncCallback。 stayAsyncCallbackClass, there areDataCallbackVoidCallbackACLCallbackStatCallbackWait for callback interface, call different interfaces according to different methods in zookeeper class. For the next several methods, this asynchronous one will be omitted, which is the same.
InterfaceprocessResult()Methods, parameters are described as follows:

  • RC: server response code, 0 indicates success, – 4 indicates disconnection between server and client, – 110 indicates node already exists, – 112 indicates session expiration
  • Path: the path of the node
  • CTX: context information passed
  • Name: the complete node path of this data node

Delete node

Test code

@Test
public void testDelete() throws KeeperException, InterruptedException {
    //The first parameter is the node path
    //The second parameter is the version of the node, and - 1 means not participating in atomic operation
    //Other callback parameters and contexts are the same as above
    zooKeeper.delete("/node", -1);
    System. Out. Println ("delete node succeeded");
}

The operation results are as follows:
API usage of zookeeper

Node list

Test code

@Test
public void testGetChildren() throws KeeperException, InterruptedException {
    //The first parameter is to get the child nodes under the node path
    //The second parameter, true indicates that the default watcher is used, and false indicates that the watcher is not used for listening. The default watcher is the watcher when the session is created
    //Other parameters, such as register watcher, callback, context, stat information, are ignored
    List<String> children = zooKeeper.getChildren("/", true);
    System.out.println(children);
}

The operation results are as follows. Before that, node addition was run, so there are three nodes:
API usage of zookeeper

get data

Test code:

@Test
public void testGetData() throws KeeperException, InterruptedException {
    //The first parameter is to get the data of this path
    //The second parameter, true indicates that the default watcher is used, and false indicates that the watcher is not used for listening. The default watcher is the watcher when the session is created.
    //The third parameter, receiving the new stat information
    byte[] data = zooKeeper.getData("/node", true, stat);
    System.out.println(stat);
    System. Out. Println ("node data is:" + new string (data));
}

The operation results are as follows:
API usage of zookeeper

Update data

Test code:

@Test
public void testSetData() throws KeeperException, InterruptedException {
    byte[] data = zooKeeper.getData("/node", true, stat);
    System. Out. Println ("node data is:" + new string (data));
    //The first parameter is to set the path of the node
    //The second parameter is to set the data of the node
    //The third parameter is to set the version of the node, - 1 means not participating in atomic operation
    zooKeeper.setData("/node", "newData".getBytes(), -1);
    data = zooKeeper.getData("/node", true, stat);
    System. Out. Println ("node data is:" + new string (data));
}

The operation results are as follows:
API usage of zookeeper

Whether the node exists

Test code:

@Test
public void testExists() throws KeeperException, InterruptedException {
    //The first parameter is the path of the node that needs to get the information
    //The second parameter, true indicates that the default watcher is used, and false indicates that the watcher is not used for listening. The default watcher is the watcher when the session is created
    System. Out. Println ("node node information:" + zookeeper. Exists ("/ node, true));
}

The operation results are as follows:
API usage of zookeeper

Watcher

When the client obtains the information of a node or its sublist, it can listen for the change information of the node or sublist by registering the watcher. It means that the watcher’s notification is one-time. Once triggered, the Watcher will fail. So if you want to keep listening, you need to repeatedly register the watcher.
Watchedevent has the following types:

  • Nodechilderchanged: triggered when the getchildren method is set and the direct child node is created or deleted
  • Childwatchremoved: triggered when the watcher set by the getchildren method is removed
  • Nodedatachanged: GetData and exists method settings, triggered when node data is modified
  • Nodechreated: set by exists method, triggered when the node is created
  • Nodedeleted: GetData and exists method settings, triggered when a node is deleted
  • Datawatchremoved: triggered when the watcher set by GetData and exists methods is deleted

Zookeeperconnect is modified to:

public class ZookeeperConnect {
    private static final String CONNECT_STRING = "172.17.0.2:2181,172.17.0.3:2181,172.17.0.4:2181";
    public static CountDownLatch countDownLatch = new CountDownLatch(1);
    static ZooKeeper zooKeeper = null;

    public static ZooKeeper getZookeeper() {
        try {
            zooKeeper = new ZooKeeper(CONNECT_STRING, 5000, new Watcher() {
                public void process(WatchedEvent watchedEvent) {
                    System.out.println("watchedEvent:" + watchedEvent);
                    if (Event.KeeperState.SyncConnected == watchedEvent.getState()) {
                        if (Event.EventType.None == watchedEvent.getType() && null == watchedEvent.getPath()) {
                            countDownLatch.countDown();
                        } else {
                            switch (watchedEvent.getType()) {
                                case NodeChildrenChanged:
                                    System.out.println("NodeChildrenChanged");
                                    try {
                                        zooKeeper.getChildren(watchedEvent.getPath(), true);
                                    } catch (KeeperException e) {
                                        e.printStackTrace();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                    break;
                                case NodeDataChanged:
                                    try {
                                        if (watchedEvent.getPath().equals("/node/node_1")) {
                                            zooKeeper.getData(watchedEvent.getPath(), true, new Stat());
                                        } else {
                                            zooKeeper.exists(watchedEvent.getPath(), true);
                                        }
                                    } catch (KeeperException e) {
                                        e.printStackTrace();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                    System.out.println("NodeDataChanged");
                                    break;
                                case NodeCreated:
                                    try {
                                        zooKeeper.exists(watchedEvent.getPath(), true);
                                    } catch (KeeperException e) {
                                        e.printStackTrace();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                    System.out.println("NodeCreated");
                                    break;
                                case NodeDeleted:
                                    System.out.println("NodeDeleted");
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            });
            System. Out. Println ("waiting");
            countDownLatch.await();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System. Out. Println ("get to connection");
        return zooKeeper;
    }
}

getChildren Watcher

Test code:

 @Test
public void testGetChildren4Watcher() throws KeeperException, InterruptedException {
    zooKeeper.getChildren("/node", true);
    System.out.println("create prepare");
    zooKeeper.create("/node/node_1", "node_1".getBytes(),
            ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    System.out.println("setData prepare");
    zooKeeper.setData("/node/node_1", "node_1_new".getBytes(), -1);
    System.out.println("delete prepare");
    zooKeeper.delete("/node/node_1", -1);
}

The operation results are as follows:
API usage of zookeeper
Listen to the sub nodes of / node. You can see that the creation and deletion of sub nodes are listened to.

getData Watcher

Test code:

@Test
public void testGetData4Watcher() throws KeeperException, InterruptedException {
    zooKeeper.create("/node/node_1", "node_1".getBytes(),
            ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    zooKeeper.getData("/node/node_1", true, stat);
    System.out.println("setData prepare");
    zooKeeper.setData("/node/node_1", "node_1_new".getBytes(), -1);
    TimeUnit.MILLISECONDS.sleep(200);
    System.out.println();
    System.out.println("delete prepare");
    zooKeeper.delete("/node/node_1", -1);
}

The operation results are as follows:
API usage of zookeeper
After listening to the / node / node 1 node, you can see that the modification and deletion of the / node / node 1 node have been monitored.

exists Watcher

Test code:

@Test
public void testExists4Watcher() throws KeeperException, InterruptedException {
    if(null==zooKeeper.exists("/node/node_2", true)){
        System.out.println("create prepare");
        zooKeeper.create("/node/node_2", "node_2".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        zooKeeper.getData("/node/node_2", true, stat);
        TimeUnit.MILLISECONDS.sleep(200);
        System.out.println();
        System.out.println("setData prepare");
        zooKeeper.setData("/node/node_2", "node_2_new".getBytes(), -1);
        TimeUnit.MILLISECONDS.sleep(200);
        System.out.println("delete prepare");
        System.out.println();
        zooKeeper.delete("/node/node_2", -1);
    }
}

The operation results are as follows:
API usage of zookeeper
After listening to / node / node 2, we can see that the creation, modification and deletion of / node / node 2 have been monitored.

Authority control

Zookeeper provides the ACL permission control mechanism, which controls the client’s control permission to the node through the ACL of the server data node.
ACL permission control mode:

  • IP: set for IP
  • Digest: the most commonly used mode, such as “Username: password”.
  • World: open to all users
  • Super: Super administrator mode
  • Auth: on behalf of authenticated users

Test code:

@Test
public void testAuth() throws IOException, KeeperException, InterruptedException {
    ZooKeeper zooKeeper1 = new ZooKeeper(ZookeeperConnect.CONNECT_STRING, 5000, null);
    zooKeeper1.addAuthInfo("digest", "name:dajun".getBytes());
    zooKeeper1.create("/node2", "node2".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL);
    System.out.println("zooKeeper1:"+new String(zooKeeper1.getData("/node2", false, stat)));

    ZooKeeper zooKeeper2 = new ZooKeeper(ZookeeperConnect.CONNECT_STRING, 5000, null);
    System.out.println("zooKeeper2:"+new String(zooKeeper2.getData("/node2", false, stat)));

}

The operation results are as follows:
API usage of zookeeper
When zokeeper2 gets node information, it throws an exception.
Let’s take a look at the special delete operation.
Test code:

@Test
public void testAuth4Delete() throws IOException, KeeperException, InterruptedException {
    ZooKeeper zooKeeper1 = new ZooKeeper(ZookeeperConnect.CONNECT_STRING, 5000, null);
    zooKeeper1.addAuthInfo("digest", "name:dajun".getBytes());
    zooKeeper1.create("/node2", "node2".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT);
    zooKeeper1.create("/node2/node2_1", "node2_1".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL);

    ZooKeeper zooKeeper2 = new ZooKeeper(ZookeeperConnect.CONNECT_STRING, 5000, null);
    try {
        zooKeeper2.delete("/node2/node2_1", -1);
    } catch (Exception e) {
        System.out.println("delete error:" + e.getMessage());
    }

    ZooKeeper zooKeeper3 = new ZooKeeper(ZookeeperConnect.CONNECT_STRING, 5000, null);
    zooKeeper3.addAuthInfo("digest", "name:dajun".getBytes());
    zooKeeper3.delete("/node2/node2_1", -1);
    System.out.println("delete /node2/node2_1 sucess");

    ZooKeeper zooKeeper4 = new ZooKeeper(ZookeeperConnect.CONNECT_STRING, 5000, null);
    zooKeeper4.delete("/node2", -1);
    System.out.println("delete /node2 sucess");
}

The operation results are as follows:
API usage of zookeeper
Zookeeper 1, with permissions set for / node2 and / node2 / node2.
Zookeeper 2, deletion failed because of no permission.
Zookeeper 3, with permission, deleted successfully.
Zookeeper 4, without permission, also deleted successfully.
It can be seen that when deleting, the function of permissions is to access its child nodes. Permissions are needed to delete them. However, for this node, you can delete it at will. Of course, read and other permissions are not allowed. They are only useful for deleting nodes.