Apache Curator簡單介紹

longmanma發表於2021-09-09

提供了一個抽象級別更高的API,來操作Zookeeper,類似Guava提供的很多工具,讓Java書寫起來更加方便。至於有沒有用,那就要看每個人自己的理解了。

1、依賴

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.8.0</version></dependency>

2、連線Zookeeper

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
client.start();

3、增刪改查

/**
 * Zookeeper的CRUD操作
 */public class CrudExamples {    /**
     * 給指定的ZNode設定值,不能巢狀建立目錄
     * 如果節點已經存在,會拋異常org.apache.zookeeper.KeeperException$NodeExistsException: KeeperErrorCode = NodeExists for /path
     */
    public static void create(CuratorFramework client, String path, byte[] payload) throws Exception {
        client.create().forPath(path, payload);
    }    /**
     * 建立臨時節點
     * 需要注意:雖說臨時節點是session失效後立刻刪除,但是並不是client一斷開連線,session就立刻會失效
     * 失效是由zk服務端控制的,每次連線時,客戶端和服務端會協商一個合理的超時時間
     * 如果超過了超時時間client都一直美哦與傳送心跳,才回真的刪除這個session建立的臨時節點
     */
    public static void createEphemeral(CuratorFramework client, String path, byte[] payload) throws Exception {
        client.create().withMode(CreateMode.EPHEMERAL).forPath(path, payload);
    }    public static String createEphemeralSequential(CuratorFramework client, String path, byte[] payload) throws Exception {        return client.create().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, payload);
    }    public static void setData(CuratorFramework client, String path, byte[] payload) throws Exception {
        client.setData().forPath(path, payload);
    }    public static void setDataAsync(CuratorFramework client, String path, byte[] payload) throws Exception {
        CuratorListener listener = new CuratorListener() {            @Override
            public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception {                if (event != null)
                    System.out.println(event.toString());
            }
        };
        client.getCuratorListenable().addListener(listener);

        client.setData().inBackground().forPath(path, payload);
    }    public static void setDataAsyncWithCallback(CuratorFramework client, BackgroundCallback callback, String path, byte[] payload) throws Exception {
        client.setData().inBackground(callback).forPath(path, payload);
    }    public static void delete(CuratorFramework client, String path) throws Exception {
        client.delete().forPath(path);
    }    public static void guaranteedDelete(CuratorFramework client, String path) throws Exception {
        client.delete().guaranteed().forPath(path);
    }    public static List<String> watchedGetChildren(CuratorFramework client, String path) throws Exception {        return client.getChildren().watched().forPath(path);
    }    public static List<String> watchedGetChildren(CuratorFramework client, String path, Watcher watcher) throws Exception {        return client.getChildren().usingWatcher(watcher).forPath(path);
    }
}

使用上面的增刪改查來測試:

public class CuratorStartupDemo {    private static CuratorFramework CLIENT;    private static final String CHARSET = "UTF-8";    static {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CLIENT = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
    }    public static void main(String[] args) throws Exception {
        CLIENT.start();
        System.out.println(CLIENT.getZookeeperClient().getConnectionTimeoutMs());

        CrudExamples.create(CLIENT, "/x", "test".getBytes(CHARSET));

        CrudExamples.createEphemeral(CLIENT, "/e", "test".getBytes(CHARSET));

        CrudExamples.setData(CLIENT, "/x", UUID.randomUUID().toString().getBytes(CHARSET));
        CrudExamples.setDataAsync(CLIENT, "/x", UUID.randomUUID().toString().getBytes(CHARSET));
        CrudExamples.setDataAsyncWithCallback(CLIENT, ((client, event) -> {
            System.out.println(event.getPath());
        }), "/x", UUID.randomUUID().toString().getBytes(CHARSET));

        CrudExamples.createEphemeralSequential(CLIENT, "/x", "test".getBytes(CHARSET));
        CrudExamples.createEphemeralSequential(CLIENT, "/x", "test".getBytes(CHARSET));
        CrudExamples.createEphemeralSequential(CLIENT, "/x", "test".getBytes(CHARSET));
        CrudExamples.createEphemeralSequential(CLIENT, "/x", "test".getBytes(CHARSET));

        CuratorListener listener = new CuratorListener() {            @Override
            public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception {                if (event != null)
                    System.out.println(event.toString());                //watcher是一次性的,每次watch後需要重新設定watcher
                if ("/x".equals(event.getPath())) {
                    CrudExamples.watchedGetChildren(CLIENT, "/x");
                }
            }
        };
        CLIENT.getCuratorListenable().addListener(listener);
        CrudExamples.watchedGetChildren(CLIENT, "/x");
        CrudExamples.create(CLIENT, "/x/a", null);
        CrudExamples.create(CLIENT, "/x/b", null);
        CrudExamples.delete(CLIENT, "/x/a");
        CrudExamples.delete(CLIENT, "/x/b");


        MyWatcher myWatcher = new MyWatcher("/x", CLIENT);
        CrudExamples.watchedGetChildren(myWatcher.curatorFramework, myWatcher.getPath(), myWatcher);

        System.out.println("task completed");        new CountDownLatch(1).await();
    }    static class MyWatcher implements Watcher {        private String path;        private CuratorFramework curatorFramework;        public MyWatcher(String path, CuratorFramework curatorFramework) {            this.path = path;            this.curatorFramework = curatorFramework;
        }        @Override
        public void process(WatchedEvent event) {
            System.out.println(event.toString());            try {                //watcher是一次性的,每次watch後需要重新設定watcher
                CrudExamples.watchedGetChildren(this.curatorFramework, this.getPath(), this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }        public String getPath() {            return path;
        }        public CuratorFramework getCuratorFramework() {            return curatorFramework;
        }
    }

}



作者:我是楊正
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2730/viewspace-2815436/,如需轉載,請註明出處,否則將追究法律責任。