欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

zookeeper原生api使用

程序员文章站 2024-01-12 13:08:04
...

转载自:https://blog.csdn.net/haoyuyang/article/details/53436625

zookeeper的javaclient可以使我们更轻松的实现对zookeeper的各种操作,要使用java操作zookeeper,需要引入zookeeper-3.4.5.jar和zkclient-0.1.jar。zookeeper-3.4.5.jar是官方提供的JAVA API,zkclient-0.1.jar则是在原生API基础上进行扩展的开源Java客户端。(zookeeper文章所需的jar包

客户端可以通过创建一个zookeeper实例来连接zookeeper服务器,Zookeeper(Arguments)方法(一共有4个构造方法,根据参数不同),参数说明如下:

connectString:连接服务器列表,用“,”分割。

sessionTimeout:心跳检测时间周期,单位毫秒。

watcher:事件处理通知器。

canBeReadOnly:标识当前会话是否支持只读。

sessionId和sessionPassword:提供连接zookeeper服务器的sessionId和密码,通过这两个参数确定唯一一台客户端,目的是可以提供重复会话。

注意:zookeeper客户端和服务器会话的建立是一个异步的过程,也就是说在程序中,程序方法在处理完客户端初始化后立即返回(即程序继续往下执行代码,这样,在大多数情况下并没有真正的构建好一个可用会话,在会话的生命周期处于“CONNECTING”时才算真正的建立完毕,所以需要使用到多线程中的一个工具类CountDownLatch)。

先看代码,代码中和后面有说明。HelloWorld入门:

    public class ZookeeperBase {  
      
        /** zookeeper地址 */  
        static final String CONNECT_ADDR = "192.168.80.88:2181,192.168.80.87:2181,192.168.80.86:2181";  
        /** session超时时间 */  
        static final int SESSION_OUTTIME = 2000;//ms   
        /** 信号量,阻塞程序执行,用于等待zookeeper连接成功,发送成功信号 */  
        static final CountDownLatch connectedSemaphore = new CountDownLatch(1);  
          
        public static void main(String[] args) throws Exception{  
              
            ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher(){  
                @Override  
                public void process(WatchedEvent event) {  
                    //获取事件的状态  
                    KeeperState keeperState = event.getState();  
                    EventType eventType = event.getType();  
                    //如果是建立连接  
                    if(KeeperState.SyncConnected == keeperState){  
                        if(EventType.None == eventType){  
                            //如果建立连接成功,则发送信号量,让后续阻塞程序向下执行  
                            connectedSemaphore.countDown();  
                            System.out.println("zk 建立连接");  
                        }  
                    }  
                }  
            });  
      
            //进行阻塞  
            connectedSemaphore.await();  
              
            System.out.println("..");  
            //创建父节点  
    //      zk.create("/testRoot", "testRoot".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);  
              
            //创建子节点,使用EPHEMERAL,主程序执行完成后该节点被删除,只在本次会话内有效,可以用作分布式锁。  
    //      zk.create("/testRoot/children", "children data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);  
              
            //获取节点信息  
    //      byte[] data = zk.getData("/testRoot", false, null);  
    //      System.out.println(new String(data));  
    //      System.out.println(zk.getChildren("/testRoot", false));  
              
            //修改节点的值,-1表示跳过版本检查,其他正数表示如果传入的版本号与当前版本号不一致,则修改不成功,删除是同样的道理。  
    //      zk.setData("/testRoot", "modify data root".getBytes(), -1);  
    //      byte[] data = zk.getData("/testRoot", false, null);  
    //      System.out.println(new String(data));         
              
            //判断节点是否存在  
    //      System.out.println(zk.exists("/testRoot/children", false));  
            //删除节点  
    //      zk.delete("/testRoot/children", -1);  
    //      System.out.println(zk.exists("/testRoot/children", false));  
              
            zk.close();                
        }  
    }  

说明:

原生的zookeeper API提供了两种创建节点的方法,同步和异步创建节点方式。

同步方式:

参数1,节点路径(名称):/nodeName。不允许递归创建节点,在父节点不存在的情况下,不允许创建子节点。

参数2,节点内容:要求类型是字节数组,也就是说不支持序列话方式,如果需要实现序列化,可使用java相关序列化框架,如Hessian,Kryo。

参数3,节点权限:使用Ids.OPEN_ACL_UNSAFE开放权限即可。

参数4,节点类型:创建节点的类型,CreateMode.*,提供了如下所示的四种节点类型:

①PERSISTENT(持久节点)

②PERSISTENT_SEQUENTIAL(持久顺序节点)

③EPHEMERAL(临时节点,本次会话有效

④EPHEMERAL_SEQUENTIAL(临时顺序节点,本次会话有效

异步方式(在同步方法参数的基础上增加两个参数):

参数5,回调方法:注册一个异步回调方法,要实现AsynCallBack.StringCallBack接口,重写processResult(int rc, String path, Object ctx, String name)方法,当节点创建完成后执行此方法。

①rc:服务端响应码,0表示调用成功、-4表示端口连接、-110表示指定节点存在、-112表示会话已过期。

②path:接口调用时传入的数据节点的路径参数。

③ctx:调用接口传入的ctx值。

④name:实际在服务端创建的节点的名称。

参数6,传递给回调方法的参数,一般为上下文(Context)信息。

zookeeper原生api使用

Watcher、ZK状态、事件类型:

zookeeper有watch事件,是一次性触发的。当watch监视的数据发生变化时,通知在创建zookeeper是设置了Watcher的客户端。Watcher类监视的事件类型和状态类型如下所示:

事件类型(znode节点相关):

①EventType.NodeCreated:节点创建

②EventType.NodeDataChanged:节点数据变更

③EventType.NodeChildrenChanged:子节点变更

④EventType.NodeDeleted:节点删除

状态类型(客户端实例相关):

①KeeperState.Disconnected:未连接

②KeeperState.SyncConnected:已连接

③KeeperState.AuthFailed:认证失败

④KeeperState.Expired:会话失效

[java] view plain copy
  1. public class ZooKeeperWatcher implements Watcher {  
  2.   
  3.     /** 定义原子变量 */  
  4.     AtomicInteger seq = new AtomicInteger();  
  5.     /** 定义session失效时间 */  
  6.     private static final int SESSION_TIMEOUT = 10000;  
  7.     /** zookeeper服务器地址 */  
  8.     private static final String CONNECTION_ADDR = "192.168.80.88:2181";  
  9.     /** zk父路径设置 */  
  10.     private static final String PARENT_PATH = "/testWatch";  
  11.     /** zk子路径设置 */  
  12.     private static final String CHILDREN_PATH = "/testWatch/children";  
  13.     /** 进入标识 */  
  14.     private static final String LOG_PREFIX_OF_MAIN = "【Main】";  
  15.     /** zk变量 */  
  16.     private ZooKeeper zk = null;  
  17.     /** 信号量设置,用于等待zookeeper连接建立之后 通知阻塞程序继续向下执行 */  
  18.     private CountDownLatch connectedSemaphore = new CountDownLatch(1);  
  19.   
  20.     /** 
  21.      * 创建ZK连接 
  22.      * @param connectAddr ZK服务器地址列表 
  23.      * @param sessionTimeout Session超时时间 
  24.      */  
  25.     public void createConnection(String connectAddr, int sessionTimeout) {  
  26.         this.releaseConnection();  
  27.         try {  
  28.             zk = new ZooKeeper(connectAddr, sessionTimeout, this);  
  29.             System.out.println(LOG_PREFIX_OF_MAIN + "开始连接ZK服务器");  
  30.             connectedSemaphore.await();  
  31.         } catch (Exception e) {  
  32.             e.printStackTrace();  
  33.         }  
  34.     }  
  35.   
  36.     /** 
  37.      * 关闭ZK连接 
  38.      */  
  39.     public void releaseConnection() {  
  40.         if (this.zk != null) {  
  41.             try {  
  42.                 this.zk.close();  
  43.             } catch (InterruptedException e) {  
  44.                 e.printStackTrace();  
  45.             }  
  46.         }  
  47.     }  
  48.   
  49.     /** 
  50.      * 创建节点 
  51.      * @param path 节点路径 
  52.      * @param data 数据内容 
  53.      * @return  
  54.      */  
  55.     public boolean createPath(String path, String data) {  
  56.         try {  
  57.             //设置监控(由于zookeeper的监控都是一次性的所以 每次必须设置监控)  
  58.             this.zk.exists(path, true);  
  59.             System.out.println(LOG_PREFIX_OF_MAIN + "节点创建成功, Path: " +   
  60.                                this.zk.create(  /**路径*/   
  61.                                                 path,   
  62.                                                 /**数据*/  
  63.                                                 data.getBytes(),   
  64.                                                 /**所有可见*/  
  65.                                                 Ids.OPEN_ACL_UNSAFE,   
  66.                                                 /**永久存储*/  
  67.                                                 CreateMode.PERSISTENT ) +     
  68.                                ", content: " + data);  
  69.         } catch (Exception e) {  
  70.             e.printStackTrace();  
  71.             return false;  
  72.         }  
  73.         return true;  
  74.     }  
  75.   
  76.     /** 
  77.      * 读取指定节点数据内容 
  78.      * @param path 节点路径 
  79.      * @return 
  80.      */  
  81.     public String readData(String path, boolean needWatch) {  
  82.         try {  
  83.             return new String(this.zk.getData(path, needWatch, null));  
  84.         } catch (Exception e) {  
  85.             e.printStackTrace();  
  86.             return "";  
  87.         }  
  88.     }  
  89.   
  90.     /** 
  91.      * 更新指定节点数据内容 
  92.      * @param path 节点路径 
  93.      * @param data 数据内容 
  94.      * @return 
  95.      */  
  96.     public boolean writeData(String path, String data) {  
  97.         try {  
  98.             System.out.println(LOG_PREFIX_OF_MAIN + "更新数据成功,path:" + path + ", stat: " +  
  99.                                 this.zk.setData(path, data.getBytes(), -1));  
  100.         } catch (Exception e) {  
  101.             e.printStackTrace();  
  102.         }  
  103.         return false;  
  104.     }  
  105.   
  106.     /** 
  107.      * 删除指定节点 
  108.      *  
  109.      * @param path 
  110.      *            节点path 
  111.      */  
  112.     public void deleteNode(String path) {  
  113.         try {  
  114.             this.zk.delete(path, -1);  
  115.             System.out.println(LOG_PREFIX_OF_MAIN + "删除节点成功,path:" + path);  
  116.         } catch (Exception e) {  
  117.             e.printStackTrace();  
  118.         }  
  119.     }  
  120.   
  121.     /** 
  122.      * 判断指定节点是否存在 
  123.      * @param path 节点路径 
  124.      */  
  125.     public Stat exists(String path, boolean needWatch) {  
  126.         try {  
  127.             return this.zk.exists(path, needWatch);  
  128.         } catch (Exception e) {  
  129.             e.printStackTrace();  
  130.             return null;  
  131.         }  
  132.     }  
  133.   
  134.     /** 
  135.      * 获取子节点 
  136.      * @param path 节点路径 
  137.      */  
  138.     private List<String> getChildren(String path, boolean needWatch) {  
  139.         try {  
  140.             return this.zk.getChildren(path, needWatch);  
  141.         } catch (Exception e) {  
  142.             e.printStackTrace();  
  143.             return null;  
  144.         }  
  145.     }  
  146.   
  147.     /** 
  148.      * 删除所有节点 
  149.      */  
  150.     public void deleteAllTestPath() {  
  151.         if(this.exists(CHILDREN_PATH, false) != null){  
  152.             this.deleteNode(CHILDREN_PATH);  
  153.         }  
  154.         if(this.exists(PARENT_PATH, false) != null){  
  155.             this.deleteNode(PARENT_PATH);  
  156.         }         
  157.     }  
  158.       
  159.     /** 
  160.      * 收到来自Server的Watcher通知后的处理。 
  161.      */  
  162.     @Override  
  163.     public void process(WatchedEvent event) {  
  164.           
  165.         System.out.println("进入 process 。。。。。event = " + event);  
  166.           
  167.         try {  
  168.             Thread.sleep(200);  
  169.         } catch (InterruptedException e) {  
  170.             e.printStackTrace();  
  171.         }  
  172.           
  173.         if (event == null) {  
  174.             return;  
  175.         }  
  176.           
  177.         // 连接状态  
  178.         KeeperState keeperState = event.getState();  
  179.         // 事件类型  
  180.         EventType eventType = event.getType();  
  181.         // 受影响的path  
  182.         String path = event.getPath();  
  183.           
  184.         String logPrefix = "【Watcher-" + this.seq.incrementAndGet() + "】";  
  185.   
  186.         System.out.println(logPrefix + "收到Watcher通知");  
  187.         System.out.println(logPrefix + "连接状态:\t" + keeperState.toString());  
  188.         System.out.println(logPrefix + "事件类型:\t" + eventType.toString());  
  189.   
  190.         if (KeeperState.SyncConnected == keeperState) {  
  191.             // 成功连接上ZK服务器  
  192.             if (EventType.None == eventType) {  
  193.                 System.out.println(logPrefix + "成功连接上ZK服务器");  
  194.                 connectedSemaphore.countDown();  
  195.             }   
  196.             //创建节点  
  197.             else if (EventType.NodeCreated == eventType) {  
  198.                 System.out.println(logPrefix + "节点创建");  
  199.                 try {  
  200.                     Thread.sleep(100);  
  201.                 } catch (InterruptedException e) {  
  202.                     e.printStackTrace();  
  203.                 }  
  204.                 this.exists(path, true);  
  205.             }   
  206.             //更新节点  
  207.             else if (EventType.NodeDataChanged == eventType) {  
  208.                 System.out.println(logPrefix + "节点数据更新");  
  209.                 System.out.println("我看看走不走这里........");  
  210.                 try {  
  211.                     Thread.sleep(100);  
  212.                 } catch (InterruptedException e) {  
  213.                     e.printStackTrace();  
  214.                 }  
  215.                 System.out.println(logPrefix + "数据内容: " + this.readData(PARENT_PATH, true));  
  216.             }   
  217.             //更新子节点  
  218.             else if (EventType.NodeChildrenChanged == eventType) {  
  219.                 System.out.println(logPrefix + "子节点变更");  
  220.                 try {  
  221.                     Thread.sleep(3000);  
  222.                 } catch (InterruptedException e) {  
  223.                     e.printStackTrace();  
  224.                 }  
  225.                 System.out.println(logPrefix + "子节点列表:" + this.getChildren(PARENT_PATH, true));  
  226.             }   
  227.             //删除节点  
  228.             else if (EventType.NodeDeleted == eventType) {  
  229.                 System.out.println(logPrefix + "节点 " + path + " 被删除");  
  230.             }  
  231.             else ;  
  232.         }   
  233.         else if (KeeperState.Disconnected == keeperState) {  
  234.             System.out.println(logPrefix + "与ZK服务器断开连接");  
  235.         }   
  236.         else if (KeeperState.AuthFailed == keeperState) {  
  237.             System.out.println(logPrefix + "权限检查失败");  
  238.         }   
  239.         else if (KeeperState.Expired == keeperState) {  
  240.             System.out.println(logPrefix + "会话失效");  
  241.         }  
  242.         else ;  
  243.   
  244.         System.out.println("--------------------------------------------");  
  245.   
  246.     }  
  247.   
  248.     /** 
  249.      * <B>方法名称:</B>测试zookeeper监控<BR> 
  250.      * <B>概要说明:</B>主要测试watch功能<BR> 
  251.      * @param args 
  252.      * @throws Exception 
  253.      */  
  254.     public static void main(String[] args) throws Exception {  
  255.   
  256.         //建立watcher  
  257.         ZooKeeperWatcher zkWatch = new ZooKeeperWatcher();  
  258.         //创建连接  
  259.         zkWatch.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);  
  260.         //System.out.println(zkWatch.zk.toString());  
  261.           
  262.         Thread.sleep(1000);  
  263.           
  264.         // 清理节点  
  265.         zkWatch.deleteAllTestPath();  
  266.           
  267.         if (zkWatch.createPath(PARENT_PATH, System.currentTimeMillis() + "")) {  
  268.               
  269.             Thread.sleep(1000);  
  270.               
  271.               
  272.             // 读取数据,在操作节点数据之前先调用zookeeper的getData()方法是为了可以watch到对节点的操作。watch是一次性的,  
  273.             // 也就是说,如果第二次又重新调用了setData()方法,在此之前需要重新调用一次。  
  274.             System.out.println("---------------------- read parent ----------------------------");  
  275.             //zkWatch.readData(PARENT_PATH, true);  
  276.               
  277.             /** 读取子节点,设置对子节点变化的watch,如果不写该方法,则在创建子节点是只会输出NodeCreated,而不会输出NodeChildrenChanged, 
  278.                 也就是说创建子节点时没有watch。 
  279.                 如果是递归的创建子节点,如path="/p/c1/c2"的话,getChildren(PARENT_PATH, ture)只会在创建c1时watch,输出c1的NodeChildrenChanged, 
  280.                 而不会输出创建c2时的NodeChildrenChanged,如果watch到c2的NodeChildrenChanged,则需要再调用一次getChildren(String path, true)方法, 
  281.                 其中path="/p/c1" 
  282.             */  
  283.             System.out.println("---------------------- read children path ----------------------------");  
  284.             zkWatch.getChildren(PARENT_PATH, true);  
  285.   
  286.             // 更新数据  
  287.             zkWatch.writeData(PARENT_PATH, System.currentTimeMillis() + "");  
  288.               
  289.             Thread.sleep(1000);  
  290.               
  291.             // 创建子节点,同理如果想要watch到NodeChildrenChanged状态,需要调用getChildren(CHILDREN_PATH, true)  
  292.             zkWatch.readData(CHILDREN_PATH, true);  
  293.             zkWatch.createPath(CHILDREN_PATH, System.currentTimeMillis() + "");  
  294.               
  295.             Thread.sleep(1000);  
  296.               
  297.             zkWatch.writeData(CHILDREN_PATH, System.currentTimeMillis() + "");  
  298.         }  
  299.           
  300.         Thread.sleep(50000);  
  301.         // 清理节点  
  302.         zkWatch.deleteAllTestPath();  
  303.         Thread.sleep(1000);  
  304.         zkWatch.releaseConnection();  
  305.     }  
  306.   
  307. }  

Watcher的特性:一次性、客户端串行执行、轻量。

一次性:对于ZK的Watcher,只需要记住一点:Zookeeper的watch事件是一次性触发的。当watch监视的数据发生变化时,通知设置了该watch的客户端,即watcher。由于zookeeper的监视都是一次性的,所以每次必须设置监控。

客户端串行执行:客户端Watcher回调的过程是一个串行同步的过程,这为我们保证了顺序,同时需要注意一点,千万不要因为一个Watcher的处理逻辑影响了这个客户端的Watcher回调。

轻量:WatchedEvent是Zookeeper整个Wacher通知机制的最小通知单元,整个数据结构只包含三部分:通知状态、事件类型和节点路径。也就是说Watcher通知非常的简单,只会告诉客户端发生了事件而不会告知其具体内容,需要客户端自己去获取,比如NodeDataChanged事件,Zookeeper只会通知客户端指定节点的数据发生了变更,而不会直接提供具体的数据内容。

Zookeeper的ACL(AUTH):

ACL(Access Control List),Zookeeper作为一个分布式协调框架,其内部存储的都是一些关乎分布式系统运行时状态的元数据,尤其是涉及到一些分布式锁、Master选举和协调等应用场景。我们需要有效的保障Zookeeper中的数据安全,Zookeeper提供了一套完善的ACL权限控制机制来保障数据的安全。

Zookeeper提供了三种模式,权限模式、授权对象、权限:

权限模式:Scheme,开发人员经常使用如下四种权限模式:

①IP:ip模式通过ip地址粒度来进行权限控制,例如配置了:ip:192.168.1.107,即表示权限控制都是针对这个ip地址的,同时也支持按网段分配,比如:192.168.1.*。

②Digest:digest是最常用的权限控制模式,也更符合对权限的认知。其类似于“username:password”形式的权限控制标识进行权限配置。Zookeeper会对形成的权限标识先后进行两次编码处理,分别是SHA-1加密算法和BASE64编码。

③World:World是一种最开放的权限控制模式。这种模式可以看做为特殊的digest,它仅仅是一个标识而已。

④Super:超级用户模式。在超级用户模式下可以对Zookeeper进行任意操作。

权限对象:指的是权限赋予给用户或者一个指定的实体,例如IP地址或机器等。在不同的模式下,授权对象是不同的。这种模式和授权对象一一对应。

权限:权限就是指那些通过权限检测后可以被允许执行的操作,在Zookeeper中,对数据的操作权限分为以下五大类:

CREATE、DELETE、READ、WRITE、ADMIN

[java] view plain copy
  1. public class ZookeeperAuth implements Watcher {  
  2.   
  3.     /** 连接地址 */  
  4.     final static String CONNECT_ADDR = "192.168.80.88:2181";  
  5.     /** 测试路径 */  
  6.     final static String PATH = "/testAuth";  
  7.     final static String PATH_DEL = "/testAuth/delNode";  
  8.     /** 认证类型 */  
  9.     final static String authentication_type = "digest";  
  10.     /** 认证正确方法 */  
  11.     final static String correctAuthentication = "123456";  
  12.     /** 认证错误方法 */  
  13.     final static String badAuthentication = "654321";  
  14.       
  15.     static ZooKeeper zk = null;  
  16.     /** 计时器 */  
  17.     AtomicInteger seq = new AtomicInteger();  
  18.     /** 标识 */  
  19.     private static final String LOG_PREFIX_OF_MAIN = "【Main】";  
  20.       
  21.     private CountDownLatch connectedSemaphore = new CountDownLatch(1);  
  22.       
  23.     @Override  
  24.     public void process(WatchedEvent event) {  
  25.         try {  
  26.             Thread.sleep(200);  
  27.         } catch (InterruptedException e) {  
  28.             e.printStackTrace();  
  29.         }  
  30.         if (event==null) {  
  31.             return;  
  32.         }  
  33.         // 连接状态  
  34.         KeeperState keeperState = event.getState();  
  35.         // 事件类型  
  36.         EventType eventType = event.getType();  
  37.         // 受影响的path  
  38.         String path = event.getPath();  
  39.           
  40.         String logPrefix = "【Watcher-" + this.seq.incrementAndGet() + "】";  
  41.   
  42.         System.out.println(logPrefix + "收到Watcher通知");  
  43.         System.out.println(logPrefix + "连接状态:\t" + keeperState.toString());  
  44.         System.out.println(logPrefix + "事件类型:\t" + eventType.toString());  
  45.         if (KeeperState.SyncConnected == keeperState) {  
  46.             // 成功连接上ZK服务器  
  47.             if (EventType.None == eventType) {  
  48.                 System.out.println(logPrefix + "成功连接上ZK服务器");  
  49.                 connectedSemaphore.countDown();  
  50.             }   
  51.         } else if (KeeperState.Disconnected == keeperState) {  
  52.             System.out.println(logPrefix + "与ZK服务器断开连接");  
  53.         } else if (KeeperState.AuthFailed == keeperState) {  
  54.             System.out.println(logPrefix + "权限检查失败");  
  55.         } else if (KeeperState.Expired == keeperState) {  
  56.             System.out.println(logPrefix + "会话失效");  
  57.         }  
  58.         System.out.println("--------------------------------------------");  
  59.     }  
  60.     /** 
  61.      * 创建ZK连接 
  62.      *  
  63.      * @param connectString 
  64.      *            ZK服务器地址列表 
  65.      * @param sessionTimeout 
  66.      *            Session超时时间 
  67.      */  
  68.     public void createConnection(String connectString, int sessionTimeout) {  
  69.         this.releaseConnection();  
  70.         try {  
  71.             zk = new ZooKeeper(connectString, sessionTimeout, this);  
  72.             //添加节点授权  
  73.             zk.addAuthInfo(authentication_type,correctAuthentication.getBytes());  
  74.             System.out.println(LOG_PREFIX_OF_MAIN + "开始连接ZK服务器");  
  75.             //倒数等待  
  76.             connectedSemaphore.await();  
  77.         } catch (Exception e) {  
  78.             e.printStackTrace();  
  79.         }  
  80.     }  
  81.       
  82.     /** 
  83.      * 关闭ZK连接 
  84.      */  
  85.     public void releaseConnection() {  
  86.         if (this.zk!=null) {  
  87.             try {  
  88.                 this.zk.close();  
  89.             } catch (InterruptedException e) {  
  90.             }  
  91.         }  
  92.     }  
  93.       
  94.     /** 
  95.      *  
  96.      * <B>方法名称:</B>测试函数<BR> 
  97.      * <B>概要说明:</B>测试认证<BR> 
  98.      * @param args 
  99.      * @throws Exception 
  100.      */  
  101.     public static void main(String[] args) throws Exception {  
  102.           
  103.         ZookeeperAuth testAuth = new ZookeeperAuth();  
  104.         testAuth.createConnection(CONNECT_ADDR,2000);  
  105.         List<ACL> acls = new ArrayList<ACL>(1);  
  106.         for (ACL ids_acl : Ids.CREATOR_ALL_ACL) {  
  107.             acls.add(ids_acl);  
  108.         }  
  109.   
  110.         try {  
  111.             zk.create(PATH, "init content".getBytes(), acls, CreateMode.PERSISTENT);  
  112.             System.out.println("使用授权key:" + correctAuthentication + "创建节点:"+ PATH + ", 初始内容是: init content");  
  113.         } catch (Exception e) {  
  114.             e.printStackTrace();  
  115.         }  
  116.         try {  
  117.             zk.create(PATH_DEL, "will be deleted! ".getBytes(), acls, CreateMode.PERSISTENT);  
  118.             System.out.println("使用授权key:" + correctAuthentication + "创建节点:"+ PATH_DEL + ", 初始内容是: init content");  
  119.         } catch (Exception e) {  
  120.             e.printStackTrace();  
  121.         }  
  122.   
  123.         // 获取数据  
  124.         getDataByNoAuthentication();  
  125.         getDataByBadAuthentication();  
  126.         getDataByCorrectAuthentication();  
  127.   
  128.         // 更新数据  
  129.         updateDataByNoAuthentication();  
  130.         updateDataByBadAuthentication();  
  131.         updateDataByCorrectAuthentication();  
  132.   
  133.         // 删除数据  
  134.         deleteNodeByBadAuthentication();  
  135.         deleteNodeByNoAuthentication();  
  136.         deleteNodeByCorrectAuthentication();  
  137.         //  
  138.         Thread.sleep(1000);  
  139.           
  140.         deleteParent();  
  141.         //释放连接  
  142.         testAuth.releaseConnection();  
  143.     }  
  144.     /** 获取数据:采用错误的密码 */  
  145.     static void getDataByBadAuthentication() {  
  146.         String prefix = "[使用错误的授权信息]";  
  147.         try {  
  148.             ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000null);  
  149.             //授权  
  150.             badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());  
  151.             Thread.sleep(2000);  
  152.             System.out.println(prefix + "获取数据:" + PATH);  
  153.             System.out.println(prefix + "成功获取数据:" + badzk.getData(PATH, falsenull));  
  154.         } catch (Exception e) {  
  155.             System.err.println(prefix + "获取数据失败,原因:" + e.getMessage());  
  156.         }  
  157.     }  
  158.   
  159.     /** 获取数据:不采用密码 */  
  160.     static void getDataByNoAuthentication() {  
  161.         String prefix = "[不使用任何授权信息]";  
  162.         try {  
  163.             System.out.println(prefix + "获取数据:" + PATH);  
  164.             ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000null);  
  165.             Thread.sleep(2000);  
  166.             System.out.println(prefix + "成功获取数据:" + nozk.getData(PATH, falsenull));  
  167.         } catch (Exception e) {  
  168.             System.err.println(prefix + "获取数据失败,原因:" + e.getMessage());  
  169.         }  
  170.     }  
  171.   
  172.     /** 采用正确的密码 */  
  173.     static void getDataByCorrectAuthentication() {  
  174.         String prefix = "[使用正确的授权信息]";  
  175.         try {  
  176.             System.out.println(prefix + "获取数据:" + PATH);  
  177.               
  178.             System.out.println(prefix + "成功获取数据:" + zk.getData(PATH, falsenull));  
  179.         } catch (Exception e) {  
  180.             System.out.println(prefix + "获取数据失败,原因:" + e.getMessage());  
  181.         }  
  182.     }  
  183.   
  184.     /** 
  185.      * 更新数据:不采用密码 
  186.      */  
  187.     static void updateDataByNoAuthentication() {  
  188.   
  189.         String prefix = "[不使用任何授权信息]";  
  190.   
  191.         System.out.println(prefix + "更新数据: " + PATH);  
  192.         try {  
  193.             ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000null);  
  194.             Thread.sleep(2000);  
  195.             Stat stat = nozk.exists(PATH, false);  
  196.             if (stat!=null) {  
  197.                 nozk.setData(PATH, prefix.getBytes(), -1);  
  198.                 System.out.println(prefix + "更新成功");  
  199.             }  
  200.         } catch (Exception e) {  
  201.             System.err.println(prefix + "更新失败,原因是:" + e.getMessage());  
  202.         }  
  203.     }  
  204.   
  205.     /** 
  206.      * 更新数据:采用错误的密码 
  207.      */  
  208.     static void updateDataByBadAuthentication() {  
  209.   
  210.         String prefix = "[使用错误的授权信息]";  
  211.   
  212.         System.out.println(prefix + "更新数据:" + PATH);  
  213.         try {  
  214.             ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000null);  
  215.             //授权  
  216.             badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());  
  217.             Thread.sleep(2000);  
  218.             Stat stat = badzk.exists(PATH, false);  
  219.             if (stat!=null) {  
  220.                 badzk.setData(PATH, prefix.getBytes(), -1);  
  221.                 System.out.println(prefix + "更新成功");  
  222.             }  
  223.         } catch (Exception e) {  
  224.             System.err.println(prefix + "更新失败,原因是:" + e.getMessage());  
  225.         }  
  226.     }  
  227.   
  228.     /** 
  229.      * 更新数据:采用正确的密码 
  230.      */  
  231.     static void updateDataByCorrectAuthentication() {  
  232.   
  233.         String prefix = "[使用正确的授权信息]";  
  234.   
  235.         System.out.println(prefix + "更新数据:" + PATH);  
  236.         try {  
  237.             Stat stat = zk.exists(PATH, false);  
  238.             if (stat!=null) {  
  239.                 zk.setData(PATH, prefix.getBytes(), -1);  
  240.                 System.out.println(prefix + "更新成功");  
  241.             }  
  242.         } catch (Exception e) {  
  243.             System.err.println(prefix + "更新失败,原因是:" + e.getMessage());  
  244.         }  
  245.     }  
  246.   
  247.     /** 
  248.      * 不使用密码 删除节点 
  249.      */  
  250.     static void deleteNodeByNoAuthentication() throws Exception {  
  251.   
  252.         String prefix = "[不使用任何授权信息]";  
  253.   
  254.         try {  
  255.             System.out.println(prefix + "删除节点:" + PATH_DEL);  
  256.             ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000null);  
  257.             Thread.sleep(2000);  
  258.             Stat stat = nozk.exists(PATH_DEL, false);  
  259.             if (stat!=null) {  
  260.                 nozk.delete(PATH_DEL,-1);  
  261.                 System.out.println(prefix + "删除成功");  
  262.             }  
  263.         } catch (Exception e) {  
  264.             System.err.println(prefix + "删除失败,原因是:" + e.getMessage());  
  265.         }  
  266.     }  
  267.   
  268.     /** 
  269.      * 采用错误的密码删除节点 
  270.      */  
  271.     static void deleteNodeByBadAuthentication() throws Exception {  
  272.   
  273.         String prefix = "[使用错误的授权信息]";  
  274.   
  275.         try {  
  276.             System.out.println(prefix + "删除节点:" + PATH_DEL);  
  277.             ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000null);  
  278.             //授权  
  279.             badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());  
  280.             Thread.sleep(2000);  
  281.             Stat stat = badzk.exists(PATH_DEL, false);  
  282.             if (stat!=null) {  
  283.                 badzk.delete(PATH_DEL, -1);  
  284.                 System.out.println(prefix + "删除成功");  
  285.             }  
  286.         } catch (Exception e) {  
  287.             System.err.println(prefix + "删除失败,原因是:" + e.getMessage());  
  288.         }  
  289.     }  
  290.   
  291.     /** 
  292.      * 使用正确的密码删除节点 
  293.      */  
  294.     static void deleteNodeByCorrectAuthentication() throws Exception {  
  295.   
  296.         String prefix = "[使用正确的授权信息]";  
  297.   
  298.         try {  
  299.             System.out.println(prefix + "删除节点:" + PATH_DEL);  
  300.             Stat stat = zk.exists(PATH_DEL, false);  
  301.             if (stat!=null) {  
  302.                 zk.delete(PATH_DEL, -1);  
  303.                 System.out.println(prefix + "删除成功");  
  304.             }  
  305.         } catch (Exception e) {  
  306.             System.out.println(prefix + "删除失败,原因是:" + e.getMessage());  
  307.         }  
  308.     }  
  309.   
  310.     /** 
  311.      * 使用正确的密码删除节点 
  312.      */  
  313.     static void deleteParent() throws Exception {  
  314.         try {  
  315.             Stat stat = zk.exists(PATH_DEL, false);  
  316.             if (stat == null) {  
  317.                 zk.delete(PATH, -1);  
  318.             }  
  319.         } catch (Exception e) {  
  320.             e.printStackTrace();  
  321.         }  
  322.     }  
  323.