JavaでZookeeperを操作するコードの例を詳しく説明します。


依存

 <dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.6.0</version>
  </dependency>
zkServerに接続

//     ,zkServer ip、port,         
  String connectStr = "192.168.1.9:2181";

  //zookeeper    zkCli
  ZooKeeper zooKeeper = null;

  try {
     //     1。          ,    :1、         ,   final;2、        ,  try  ,  final;3、  try ,  final
     CountDownLatch countDownLatch = new CountDownLatch(1);
    //    ms,   
    zooKeeper = new ZooKeeper(connectStr, 5000, new Watcher() {
      public void process(WatchedEvent watchedEvent) {
        //         
        if (watchedEvent.getState().equals(Event.KeeperState.SyncConnected)) {
          System.out.println("    ");
          //  -1
          countDownLatch.countDown();
        }
      }
    });
    //  ,   0         。            ,    zk
    countDownLatch.await();
  } catch (IOException | InterruptedException e) {
    e.printStackTrace();
  }


  //...  zk。   demo       


  //    
  try {
    zooKeeper.close();
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
ノードが存在するかどうかを検出

//         

  //     
  Stat exists = null;
  try {
    //    ,      Stat;     ,  null。      watch
    exists = zooKeeper.exists("/mall",false);
  } catch (KeeperException | InterruptedException e) {
    e.printStackTrace();
  }
  if (exists==null){
    System.out.println("     ");
  }
  else {
    System.out.println("    ");
  }


  //    
  zooKeeper.exists("/mall",false, new AsyncCallback.StatCallback() {
    //    path znode  ,    ctx       ,    znode   
    public void processResult(int i, String s, Object o, Stat stat) {
      //       ,   stat null
      if (stat==null){
        System.out.println("     ");
      }
      else{
        System.out.println("    ");
      }
    }
  //   ctx,Object  
  },null);
操作後、サービス側は処理結果に戻り、void、nullに戻っても処理結果を計算します。
同期とは、現在のスレッドがブロックされていて、サーバーがデータを返すのを待って、戻ってきたデータを受け取ってから続けて実行します。
非同期コールとは、結果(戻りデータ)の処理をコールバック関数に書き込み、現在スレッドが戻りを待っていないデータを続けて実行し、戻ってきたデータを受信すると自動的にコールバック関数を呼び出して処理することです。
データのコードを返した後の処理が、リターンデータやリターンデータの処理に依存しない場合、リターンデータの処理をコールバック関数として作成することができます。
ノードを作成

//    

  //    
  try {
    //     byte[],       null;  acl    ZooDefs.Ids.OPEN_ACL_UNSAFE;         ,P   ,E   ,S   
    zooKeeper.create("/mall", "abcd".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    System.out.println("     /mall");
    //       ,     
  } catch (KeeperException | InterruptedException e) {     System.out.println("    /mall  ,          ");
    e.printStackTrace();
  }

  //    
  zooKeeper.create("/mall", "abcd".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, new AsyncCallback.Create2Callback(){
    //   path,   ctx,       
    public void processResult(int i, String s, Object o, String s1, Stat stat) {
      //         ,   stat        ,       ,   stat null
      if (stat==null){
        System.out.println("    /mall  ,          ");
      }
      else {
        System.out.println("      ");
      }
    }
    //ctx  
  },null);
ノードを削除

//    

  //    
  try {
    //         ,-1         
    zooKeeper.delete("/mall1",-1);
    System.out.println("      /mall");
  } catch (InterruptedException | KeeperException e) {
    System.out.println("    /mall  ");
    e.printStackTrace();
  }


  //    
  zooKeeper.delete("/mall2", -1, new AsyncCallback.VoidCallback() {
    //    path,    ctx
    public void processResult(int i, String s, Object o) {
      
    }
  //
  //ctx  
  },null);
delete()は、サブノードがないznodeだけ削除します。このznodeにサブノードがあると、異常を投げます。
再帰的にサブノードを削除する方法が提供されていません。サブノードを有するznodeを削除するには、再帰的削除を自分で実現する必要があります。先にサブノードリストをGET_Children()に取得し、リストを巡回してサブノードを削除し、親ノードを削除しても良い。
サブノードリストを取得

//       ,List<String>,  /mall/user,/mall/order,    ["user"、"order"]

  //    
  List<String> children = null;
  try {
    //      watch
    children = zooKeeper.getChildren("/mall", false);
  } catch (KeeperException | InterruptedException e) {
    e.printStackTrace();
  }
  System.out.println("     :" + children);


  //  
  zooKeeper.getChildren("/mall", false, new AsyncCallback.ChildrenCallback() {
    //       :path、ctx、        
    public void processResult(int i, String s, Object o, List<String> list) {
      System.out.println("     :" + list);
    }
  //ctx  
  }, null);
サブノードのみを取得し、孫ノードを取得しません。
watchは全部です。bootleanを書いてもいいです。モニターを追加してtrueを書いて、falseを書いてもいいです。Watchオブジェクトを書いてもいいです。newの一つのWatchのオブジェクトは傍受すると表しています。nullは傍受しないと表しています。
ノードデータの取得

//      ,  byte[]

  //    
  byte[] data = null;
  try {
    //      watch,    stat
    data = zooKeeper.getData("/mall", false, null);
  } catch (KeeperException | InterruptedException e) {
    e.printStackTrace();
  }
  //  new String()    data   null,   null  NPE
  if (data==null){
    System.out.println("       ");
  }
  else{
    System.out.println("    :"+new String(data));
  }


  //    
  zooKeeper.getData("/mall", false, new AsyncCallback.DataCallback() {
    //       :path、ctx、       、    
    public void processResult(int i, String s, Object o, byte[] bytes, Stat stat) {
      //    bytes   null,        ,        ;    ,  bytes  null
      System.out.println("    :" + new String(bytes) );
    }
    //ctx  
  }, null);
ノードデータの変更を設定する

//  |     

  //    
  try {
    //          
    zooKeeper.setData("/mall", "1234".getBytes(), -1);
    System.out.println("        ");
  } catch (KeeperException | InterruptedException e) {
    System.out.println("        ");
    e.printStackTrace();
  }


  //    
  zooKeeper.setData("/mall", "1234".getBytes(), -1, new AsyncCallback.StatCallback() {
    //    path,    ctx
    public void processResult(int i, String s, Object o, Stat stat) {

    }
  // ctx
  },null);
acl権限の設定

//  acl  
    
  //         ,    Id  
  ACL acl = new ACL(ZooDefs.Perms.ALL, new Id("auth", "chy:abcd"));
  
  List<ACL> aclList = new ArrayList<>();
  aclList.add(acl);
  
  //  List     ACL  ,      
  //List<ACL> aclList = Collections.singletonList(auth);
    
  //    ,         。          ,               
  zooKeeper.addAuthInfo("digest","chy:abcd".getBytes());

  
  //    setAcl
  try {
    //      List<ACL>,         
    zooKeeper.setACL("/mall", aclList, -1);
    System.out.println("      ");
  } catch (KeeperException | InterruptedException e) {
    System.out.println("      ");
    e.printStackTrace();
  }

  
  //              
  try {
    zooKeeper.create("/mall","abcd".getBytes(),aclList,CreateMode.PERSISTENT);
    System.out.println("          ");
  } catch (KeeperException | InterruptedException e) {
    e.printStackTrace();
  }
権限を設定した後、zkServerに接続して操作する場合は、まずユーザーを検証する必要があります。
ここには対応する非同期のコールバックが書かれていません。
acl権限を表示

//  acl  
    
  //      ,            ,  session       
  zooKeeper.addAuthInfo("digest","chy:abcd".getBytes());

  
  //    
  try {
    List<ACL> aclList = zooKeeper.getACL("/mall", null);
    System.out.println("acl  :"+aclList);
  } catch (KeeperException | InterruptedException e) {
    System.out.println("  acl    ");
    e.printStackTrace();
  }


  //    
  zooKeeper.getACL("/mall3", null, new AsyncCallback.ACLCallback() {
    //    :path、ctx、    List<ACL>、    
    public void processResult(int i, String s, Object o, List<ACL> list, Stat stat) {
      //        acl  ,       
      System.out.println("acl  :"+list);
    }
  //ctx  
  },null);
モニターを追加

//        
  try {
    CountDownLatch countDownLatch = new CountDownLatch(1);

    zooKeeper.getData("/mall", new Watcher() {
      public void process(WatchedEvent watchedEvent) {
        //watcher           ,            process()   ,           
        if (watchedEvent.getType().equals(Event.EventType.NodeDataChanged)){
          System.out.println("       ");
          //     ,           ,             
          //countDownLatch.countDown();
        }
      }
    }, null);
    //  watcher     ,       ,    CountDownLatch
    countDownLatch.await();
  } catch (KeeperException | InterruptedException e) {
    e.printStackTrace();
  }
Zoo Keeper類のexists()、get Data()、get Children()方法はすべて傍受機能を追加しています。使い方は似ています。
watttcheevent.getType().equals(Event.Event Type.NodeData Chend)
wattchedEvent.getState().equals(Event.Keeper Sttes.SyncConneced)
getTypeはイベントタイプを取得し、getStateは接続状態を取得します。
以上のように、子孫ノードを再帰的に監視し、子孫ノードのデータ変更もNodeData Changedとし、子孫ノードの作成|削除もNodeCreated NodeDeletedとしてカウントされる。

//          
   try {
    CountDownLatch countDownLatch1 = new CountDownLatch(1);
    zooKeeper.addWatch("/mall", new Watcher() {
      @Override
      public void process(WatchedEvent watchedEvent) {
        if (watchedEvent.getType().equals(Event.EventType.NodeDataChanged)){
          System.out.println("       ");
          //           ,          
          //countDownLatch1.countDown();
        }
      }
    //    ,PERSISTENT        ,PERSISTENT_RECURSIVE         
    }, AddWatchMode.PERSISTENT_RECURSIVE);
    countDownLatch1.await();
  } catch (KeeperException | InterruptedException e) {
    e.printStackTrace();
  }
count Down Latch 1.await()スレッドをブロックするには、新しいスレッドを起動してモニターしたほうがいいです。
モニターが設置されているzkCliだけが、ノードにイベントが発生した時にzkServerから通知があります。
watchはzkServerのメモリにのみ保存されています(zkはjdkに依存しています。jvmで実行しています。ヒープの中のsessionオブジェクト)。ハードディスクには耐久性がありません。つまり設定されたモニターは今回のセッション期間だけ有効です。zkCliは接続をオフしています。
待ち受けを削除

//        
  try {
    zooKeeper.addWatch("/mall",null,AddWatchMode.PERSISTENT);
    System.out.println("     ");
  } catch (KeeperException | InterruptedException e) {
    e.printStackTrace();
  }
上にモニターを追加する方法です。ウォッチウォッチパラメータは、bootleanタイプなら、falseに設定すれば傍受をオフできます。Watchタイプなら、nullで上書きする前に設定したモニターを設定できます。

//        
  try {
    //      Watcher,       Watcher    ,   null
    //                ,Any       ,Data         ,Children            
    //            zkServe ,          
    zooKeeper.removeWatches("/mall",watcher, Watcher.WatcherType.Children,true);
  } catch (InterruptedException | KeeperException e) {
    e.printStackTrace();
  }
傍受は2部構成で、一部はzkServerで、イベント発生時に対応するzkCliを通知します。一部はzkCliでzkServerの通知を受けた時にいくつかの処理を行います。
最後のパラメータ指定はzkServerに接続されていません。ローカル(zkCli)の傍受部分を削除するかどうか、true――除去します。false――除去しません。
例えばzkServerに接続されていません。ローカルモニターを削除して、10つの心拍内にzkServerを接続しました。zkServerの傍受部分はまだあります。イベントが発生した時はこのzkCliを通知しますが、zkCliローカルモニターはすでに除去されました。通知に対しては処理しません。
第一の方法は全体の傍受を除去し、傍受対象のウォッチに入る必要がない。
第二の方式の機能はより完全で、傍受のどの部分を削除するかを指定できますが、watchオブジェクトに入る必要があります。傍受を追加する時は変数を使ってwatchオブジェクトを保存します。
ここでは、JavaでZookeeperを操作する際のコード例についての詳細な文章を紹介します。Java操作Zookeeperの内容については、以前の文章を検索したり、下記の関連記事を引き続き閲覧したりしてください。これからもよろしくお願いします。