Zookeeper client (5)-Curator

In the Zookeeper client (4)-Curator , we introduced the node operation of the Curator client, as well as asynchronous operations and transaction operations, but we did not introduce how to monitor node changes in Curator, similar to ZkClient. It also provides us with a listener. Cache is a package for event monitoring in curator. The monitoring of events can be viewed as a comparison process between the local cache view and the remote zookeeper view.

  • NodeCache: Node cache is used to handle changes in the node itself, callback interface NodeCacheListener
  • PathChildrenCache: The child node cache is used to handle the child node changes of the node, and the callback interface PathChildrenCacheListener
  • TreeCache: The combination of NodeCache and PathChildrenCache, callback interface TreeCacheListener



NodeCache

First of all, let ’s take a look at NodeCache. We follow the steps of Curator to Zookeeper introduced last time. First, we will first connect to Zookeeper. Then we add a listener as follows:

public class CuratorTest {
    private static final String CONNENT_ADDR = "192.168.80.130:2181";

    public static void main(String[] args) throws Exception {
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
                .connectString(CONNENT_ADDR)
                .connectionTimeoutMs(5000)  //连接超时时间
                .sessionTimeoutMs(5000)     //会话超时时间
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                .build();
        curatorFramework.start();

        final NodeCache cache = new NodeCache(curatorFramework, "/node1", false);
        cache.start();	//需要调用nodeCache的start方法能进行缓存和事件监听

        cache.getListenable().addListener(new NodeCacheListener() {
            //监听节点变化
            @Override
            public void nodeChanged() throws Exception {
                System.out.println("路径为:" + cache.getCurrentData().getPath());
                System.out.println("数据为:" + new String(cache.getCurrentData().getData()));
                System.out.println("状态为:" + cache.getCurrentData().getStat());
            }
        });

        curatorFramework.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .forPath("/node1", "value".getBytes());

        Thread.sleep(1000);
    }
}

Insert picture description here
The first parameter is the frame client passed into the created Curator, the second parameter is the path of the listening node, and the third overload parameter dataIsCompressed indicates whether to compress the data. Finally, you must call the start method of NodeCache to perform caching and event monitoring.

Insert picture description here
Here we find that if the node monitored by NodeCache is empty (that is, the incoming path does not exist). Then if we create the corresponding node later, it will also trigger an event to call back the nodeChanged method.




In addition, the event monitoring method cache.start () of the startup node can also pass parameters, which defaults to false, as follows

void start (boolean buildInitial) // true means to cache the current node

The only parameter, buildInitial, represents whether to cache the node's data immediately. If it is set to true, you can get the information of the corresponding node ChildData class by calling the GetCurrentData method of NodeCache immediately when start is started. If it is set to false, you cannot get the corresponding information.
Insert picture description here
Insert picture description here
When testing false as above, try to add a sleep time in the front, otherwise you may not get the expected results, because the interval may be too short and only trigger an event.



Insert picture description here
Insert picture description here




PathChildrenCache

After understanding the changes of Curator listening nodes, let's take a look at how Curator listens for the addition, modification and deletion of child nodes

public class CuratorTest {
    private static final String CONNENT_ADDR = "192.168.80.130:2181";

    public static void main(String[] args) throws Exception {
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
                .connectString(CONNENT_ADDR)
                .connectionTimeoutMs(5000)  //连接超时时间
                .sessionTimeoutMs(5000)     //会话超时时间
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                .build();
        curatorFramework.start();

        final PathChildrenCache cache = new PathChildrenCache(curatorFramework, "/node1", true);
        cache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);//只有POST_INITIALIZED_EVENT模式才会启用监听功能

        cache.getListenable().addListener(new PathChildrenCacheListener() {
            //监听子节点的变化
            @Override
            public void childEvent(CuratorFramework cf, PathChildrenCacheEvent event) throws Exception {
                switch (event.getType()) {
                    case CHILD_ADDED:    //新增
                        System.out.println("新增子节点路径:" + event.getData().getPath());
                        System.out.println("新增子节点数据:" + new String(event.getData().getData()));
                        break;
                    case CHILD_UPDATED:  //更新
                        System.out.println("更新子节点路径:" + event.getData().getPath());
                        System.out.println("更新子节点数据:" + new String(event.getData().getData()));
                        break;
                    case CHILD_REMOVED:  //移除
                        System.out.println("移除子节点路径:" + event.getData().getPath());
                        System.out.println("移除子节点数据:" + new String(event.getData().getData()));
                        break;
                    default:
                        break;
                }
            }
        });

        curatorFramework.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .forPath("/node1/n1", "v1".getBytes());
        
        Thread.sleep(2000);
    }
}

Insert picture description here


Here we pay a little attention, that is the third parameter cacheData in the figure below, which is different from the NodeCache we introduced above. Here it indicates whether to cache the node content. If cacheData is true, then the node content will be obtained at the same time when the node list change event is received.
Insert picture description here
In addition, after creating an instance of PathChildrenCacheListener, you need to register this instance to the PathChildrenCache cache instance and use the addListener method of the cache instance. Then use the start method of the cache instance nodeCache to start the event monitoring of the node.


The start method here needs to pass in the starting mode. Three modes can be introduced:

  • NORMAL: When the asynchronous initialization cache is
    started, the cache is initialized asynchronously, and no notification will be issued after completion.

  • BUILD_INITIAL_CACHE: When the synchronous initialization cache
    starts, the synchronous initialization cache, and after creating the cache, pull the corresponding data from the server.

  • POST_INITIALIZED_EVENT: Initialize the cache asynchronously and trigger the completion event. At
    startup, asynchronously initialize the cache. The initialization completion triggers the PathChildrenCacheEvent.Type # INITIALIZED event. The Listener in the cache will receive a notification of the event.




In addition, PathChildrenCache monitors the addition, modification, and deletion of child nodes. It is basically similar to ZkClient.

  • Can only listen to child nodes, not the current node
  • Can't listen recursively, the child nodes under the child node can't monitor recursively

But there is a slight difference here. In ZkClient, we are operating the child node under the child node, our listener will not have any trigger events, but in Curator we are operating the child node under the child node, the listener It will be felt, but it can not get the information of the child nodes under the child node, as follows:
Insert picture description here




TreeCache

Above we know that NodeCache is used to observe the ZNode itself. If the ZNode node itself is created, updated or deleted, then the Node Cache will update the cache and trigger an event to the registered listener. The interface corresponding to the listener is NodeCacheListener.


PathChildrenCache child node cache is used to observe the child nodes of ZNode and cache the state of child nodes. If the child nodes of ZNode are created, updated or deleted, then PathChildrenCache will update the cache and trigger an event to the registered listener. The interface is PathChildrenCacheListener.


TreeCache can be seen as a combination of the above two. TreeCache observes all the data of the current ZNode node. TreeCache can not only monitor child nodes, but also the node itself.


Its usage is basically similar to PathChildrenCache, except that it corresponds to the addition, modification, and deletion of nodes. The method name of the event type of TreeCache is different.
Insert picture description here

286 original articles published · Liked12 · Visitors 10,000+

Guess you like

Origin blog.csdn.net/newbie0107/article/details/105445912