zookeeper-curator的使用(7)

Zookeeper框架curator

​ Curator是Netflix公司開源的一套zookeeper客戶端框架,以原生API爲基礎進行了包裝,解決了很多Zookeeper客戶端非常底層的細節開發工作,包括連接重連、反覆註冊Watcher和NodeExistsException異常等等,實現了Fluent風格的API接口

  • curator的特點

    ​ 先說說zookeeper原生API存在的不便性,連接對象的異步創建,需要開發自行編碼創建等待,連接沒有自動連接超時機制,watcher一次註冊生效一次

    ​ 在此基礎上,curator解決了session會話的超時重連,watcher的反覆註冊,Fluent風格的簡化了開發的API,並且也提供了分佈式鎖服務,共享計數器,緩存機制等等

  • curator pom.xml

<!-- 對zookeeper的底層api的一些封裝 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<!-- 封裝了一些高級特性,如:Cache事件監聽、選舉、分佈式鎖、分佈式Barrier -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.1</version>
</dependency>

  • 連接zookeeper
/**
 * @Author: zxx
 * @Date: 2020/4/6 10:32
 * @Description:
 * 連接的重試策略四種:
 * 1,每三秒重連一次,只會重連一次
 *  RetryPolicy retryPolicy = new RetryOneTime(3000);
 * 2, 每三秒重連一次,重連三次
 * RetryPolicy retryPolicy = new RetryNTimes(3,3000);
 * 3,每三秒重連一次,總等待時間超過十秒後停止重連
 * RetryPolicy retryPolicy = RetryUntilElapsed(10000,3000);
 * 4,隨着重連次數的增加會隨着重連時間增加
 * this.baseSleepTimeMs * Math.max(1, this.random.nextInt(1 << retryCount + 1));
 * RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
 *
 */
public class ZKconnect {

    public static void main(String[] args) {
        String zkIP = "192.168.21.141:2181";
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(zkIP)
                //會話超時時間
                .sessionTimeoutMs(10000)
                //重連機制
                .retryPolicy(retryPolicy)
                //命名空間
                .namespace("create")
                .build();
        client.start();
        System.out.println(client.isStarted());
        client.close();
    }

}
  • 新增節點
/**
 * @Author: zxx
 * @Date: 2020/4/6 11:12
 * @Description: 新增節點
 */
public class ZKCuratorCreate {
    String zkIP = "192.168.21.141:2181";
    CuratorFramework client;
    @Before
    public void before(){
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
        client = CuratorFrameworkFactory.builder()
                .connectString(zkIP)
                //會話超時時間
                .sessionTimeoutMs(10000)
                //重連機制
                .retryPolicy(retryPolicy)
                //命名空間
                .namespace("create")
                .build();
        client.start();

    }
    public void after(){
        client.close();
    }

    @Test
    public void test1() throws Exception {
        byte[] data = "node1".getBytes();
        client.create()
                //節點類型
//                CreateMode:
//                  PERSISTENT(0, false, false),
//                  PERSISTENT_SEQUENTIAL(2, false, true),
//                  EPHEMERAL(1, true, false),
//                  EPHEMERAL_SEQUENTIAL(3, true, true);
                .withMode(CreateMode.EPHEMERAL)
                //節點的權限列表 world:anyone:cdrwa
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                .forPath("/node",data);
        System.out.println("結束");
    }

    // 異步方式創建節點
    public void test2() throws Exception {
        client.create()
                // 遞歸節點的創建
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                // 異步回調接口
                .inBackground(new BackgroundCallback() {
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        // 節點的路徑
                        System.out.println(curatorEvent.getPath());
                        // 時間類型
                        System.out.println(curatorEvent.getType());
                    }
                })
                .forPath("/node4","node4".getBytes());
        Thread.sleep(5000);
        System.out.println("結束");
    }

}

  • 刪除節點
  @Test
    public void delete1() throws Exception {
       // 刪除節點
        client.delete()
                // 節點的路徑
                .forPath("/node1");
        System.out.println("結束");
    }


    @Test
    public void delete2() throws Exception {
        client.delete()
                // 版本號
                .withVersion(0)
                .forPath("/node1");
        System.out.println("結束");
    }

    @Test
    public void delete3() throws Exception {
        //刪除包含字節點的節點
        client.delete()
                .deletingChildrenIfNeeded()
                .withVersion(-1)
                .forPath("/node1");
        System.out.println("結束");
    }

    @Test
    public void delete4() throws Exception {
        // 異步方式刪除節點
        client.delete()
                .deletingChildrenIfNeeded()
                .withVersion(-1)
                .inBackground(new BackgroundCallback() {
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        // 節點路徑
                        System.out.println(curatorEvent.getPath());
                        // 事件類型
                        System.out.println(curatorEvent.getType());
                    }
                })
                .forPath("/node1");
        Thread.sleep(5000);
        System.out.println("結束");
    }
  • 更新節點
 @Test
    public void set1() throws Exception {
        // 更新節點
        client.setData()
                // arg1:節點的路徑
                // arg2:節點的數據
                .forPath("/node1", "node11".getBytes());
        System.out.println("結束");
    }

    @Test
    public void set2() throws Exception {
        client.setData()
                // 指定版本號
                .withVersion(2)
                .forPath("/node1", "node1111".getBytes());
        System.out.println("結束");
    }

    @Test
    public void set3() throws Exception {
        // 異步方式修改節點數據
        client.setData()
                .withVersion(-1)
                .inBackground(new BackgroundCallback() {
            public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                // 節點的路徑
                System.out.println(curatorEvent.getPath());
                // 事件的類型
                System.out.println(curatorEvent.getType());
            }
        }).forPath("/node1", "node1".getBytes());
        Thread.sleep(5000);
        System.out.println("結束");
    }
  • 查看節點
   @Test
    public void get1() throws Exception {
        // 讀取節點數據
        byte [] bys=client.getData()
                 // 節點的路徑
                .forPath("/node1");
        System.out.println(new String(bys));
    }

    @Test
    public void get2() throws Exception {
        // 讀取數據時讀取節點的屬性
        Stat stat=new Stat();
        byte [] bys=client.getData()
                // 讀取屬性
                .storingStatIn(stat)
                .forPath("/node1");
        System.out.println(new String(bys));
        System.out.println(stat.getVersion());
    }

    @Test
    public void get3() throws Exception {
        // 異步方式讀取節點的數據
        client.getData()
                 .inBackground(new BackgroundCallback() {
                     public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                         // 節點的路徑
                         System.out.println(curatorEvent.getPath());
                         // 事件類型
                         System.out.println(curatorEvent.getType());
                         // 數據
                         System.out.println(new String(curatorEvent.getData()));
                     }
                 })
                .forPath("/node1");
        Thread.sleep(5000);
        System.out.println("結束");
    }
  • 查看子幾點
  @Test
    public void getChild1() throws Exception {
        // 讀取子節點數據
        List<String> list = client.getChildren()
                // 節點路徑
                .forPath("/get");
        for (String str : list) {
            System.out.println(str);
        }
    }

    @Test
    public void getChild2() throws Exception {
        // 異步方式讀取子節點數據
        client.getChildren()
                .inBackground(new BackgroundCallback() {
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        // 節點路徑
                        System.out.println(curatorEvent.getPath());
                        // 事件類型
                        System.out.println(curatorEvent.getType());
                        // 讀取子節點數據
                        List<String> list=curatorEvent.getChildren();
                        for (String str : list) {
                            System.out.println(str);
                        }
                    }
                })
                .forPath("/get");
        Thread.sleep(5000);
        System.out.println("結束");
    }

  • 檢查節點是否存在
  @Test
    public void exists1() throws Exception {
        // 判斷節點是否存在
       Stat stat= client.checkExists()
                 // 節點路徑
                .forPath("/node2");
        System.out.println(stat.getVersion());
    }

    @Test
    public void exists2() throws Exception {
        // 異步方式判斷節點是否存在
        client.checkExists()
                 .inBackground(new BackgroundCallback() {
                     public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                         // 節點路徑
                         System.out.println(curatorEvent.getPath());
                         // 事件類型
                         System.out.println(curatorEvent.getType());
                         System.out.println(curatorEvent.getStat().getVersion());
                     }
                 })
                .forPath("/node2");
        Thread.sleep(5000);
        System.out.println("結束");
    }
  • watcher

    curator 提供了兩種watcher來監聽節點的變化

    • NodeCache:只是監聽某一種特定的節點,監聽節點的新增和修改
    • PathChildrenCache:監控一個znode的子節點,當一個子節點刪除,更新,刪除時,Path Cache 會改變它的狀態,會包含最新的子節點,子節點的數據和狀態
 @Test
    public void watcher1() throws Exception {
        // 監視某個節點的數據變化
        // arg1:連接對象
        // arg2:監視的節點路徑
        //watcher是可以使用多次的
       final NodeCache nodeCache=new NodeCache(client,"/watcher1");
        // 啓動監視器對象
        nodeCache.start();
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            // 節點變化時回調的方法
            public void nodeChanged() throws Exception {
                System.out.println(nodeCache.getCurrentData().getPath());
                System.out.println(new String(nodeCache.getCurrentData().getData()));
            }
        });
        Thread.sleep(100000);
        System.out.println("結束");
        //關閉監視器對象
        nodeCache.close();
    }

    @Test
    public void watcher2() throws Exception {
         // 監視子節點的變化
        // arg1:連接對象
        // arg2:監視的節點路徑
        // arg3:事件中是否可以獲取節點的數據
        PathChildrenCache pathChildrenCache=new PathChildrenCache(client,"/watcher1",true);
        // 啓動監聽
        pathChildrenCache.start();
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            // 當子節點方法變化時回調的方法
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
                // 節點的事件類型
                System.out.println(pathChildrenCacheEvent.getType());
                // 節點的路徑
                System.out.println(pathChildrenCacheEvent.getData().getPath());
                // 節點數據
                System.out.println(new String(pathChildrenCacheEvent.getData().getData()));
            }
        });
        Thread.sleep(100000);
        System.out.println("結束");
        // 關閉監聽
        pathChildrenCache.close();

    }
  • 事務
 @Test
    public void tra1() throws Exception {
        // 開啓事務
        client.inTransaction()
                .create().forPath("/node1","node1".getBytes())
                .and()
                .create().forPath("/node2","node2".getBytes())
                .and()
                //事務提交
                .commit();
    }
  • curator實現分佈式鎖
    • InterProcessMutex: 分佈式可重入排他鎖
    • InterProcessReadWriteLock:分佈式讀寫鎖

    @Test
    public void lock1() throws Exception {
        // 排他鎖
        // arg1:連接對象
        // arg2:節點路徑
        InterProcessLock interProcessLock = new InterProcessMutex(client, "/lock1");
        System.out.println("等待獲取鎖對象!");
        // 獲取鎖
        interProcessLock.acquire();
        for (int i = 1; i <= 10; i++) {
            Thread.sleep(3000);
            System.out.println(i);
        }
        // 釋放鎖
        interProcessLock.release();
        System.out.println("等待釋放鎖!");
    }

	//讀鎖
    @Test
    public void lock2() throws Exception {
        // 讀寫鎖
        InterProcessReadWriteLock interProcessReadWriteLock=new InterProcessReadWriteLock(client, "/lock1");
        // 獲取讀鎖對象
        InterProcessLock interProcessLock=interProcessReadWriteLock.readLock();
        System.out.println("等待獲取鎖對象!");
        // 獲取鎖
        interProcessLock.acquire();
        for (int i = 1; i <= 10; i++) {
            Thread.sleep(3000);
            System.out.println(i);
        }
        // 釋放鎖
        interProcessLock.release();
        System.out.println("等待釋放鎖!");
    }

	//寫鎖
    @Test
    public void lock3() throws Exception {
        // 讀寫鎖
        InterProcessReadWriteLock interProcessReadWriteLock=new InterProcessReadWriteLock(client, "/lock1");
        // 獲取寫鎖對象
        InterProcessLock interProcessLock=interProcessReadWriteLock.writeLock();
        System.out.println("等待獲取鎖對象!");
        // 獲取鎖
        interProcessLock.acquire();
        for (int i = 1; i <= 10; i++) {
            Thread.sleep(3000);
            System.out.println(i);
        }
        // 釋放鎖
        interProcessLock.release();
        System.out.println("等待釋放鎖!");
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章