使用Zookeeper原生API操作Zookeeper(轉改-練習)

    大家還記得在我的博客 《基於hadoop2.6.5搭建5個節點的分佈式集羣—(六)安裝Zookeeper 安裝部署zookeeper的五個服務器吧,如下:

    192.168.159.129:2181   192.168.159.130:2181  192.168.159.131:2181  192.168.159.132:2181  192.168.159.133:2181

    對這個服務器集羣使用Zookeeper原生API操作Zookeeper,代碼練一把吧!

   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入門:

import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class BillyTest {
    
    /** zookeeper地址 */  
    static final String CONNECT_ADDR = "192.168.159.129:2181,192.168.159.130:2181,192.168.159.131:2181,192.168.159.132:2181,192.168.159.133:2181";  

    /** session超時時間 */  
    static final int SESSION_OUTTIME = 3000;//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.delete("/testRoot", -1);
        //創建父節點  
        //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[] data2 = zk.getData("/testRoot", false, null);  
        //System.out.println(new String(data2));         
          
        //判斷節點是否存在  
        //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)信息。


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:會話失效

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class ZooKeeperWatcher  implements Watcher {
       /** 定義原子變量 */  
    AtomicInteger seq = new AtomicInteger();  
    /** 定義session失效時間 */  
    private static final int SESSION_TIMEOUT = 10000;  
    /** zookeeper服務器地址 */  
    private static final String CONNECTION_ADDR = "192.168.159.129:2181,192.168.159.130:2181,192.168.159.131:2181,192.168.159.132:2181,192.168.159.133:2181";  
    /** zk父路徑設置 */  
    private static final String PARENT_PATH = "/testWatch";  
    /** zk子路徑設置 */  
    private static final String CHILDREN_PATH = "/testWatch/children";  
    /** 進入標識 */  
    private static final String LOG_PREFIX_OF_MAIN = "【Main】";  
    /** zk變量 */  
    private ZooKeeper zk = null;  
    
    /** 信號量設置,用於等待zookeeper連接建立之後 通知阻塞程序繼續向下執行 */  
    private CountDownLatch connectedSemaphore = new CountDownLatch(1);  
  
    /** 
     * 創建ZK連接 
     * @param connectAddr ZK服務器地址列表 
     * @param sessionTimeout Session超時時間 
     */  
    public void createConnection(String connectAddr, int sessionTimeout) {  
        this.releaseConnection();  
        try {  
            zk = new ZooKeeper(connectAddr, sessionTimeout, this);  
            System.out.println(LOG_PREFIX_OF_MAIN + "開始連接ZK服務器");  
            connectedSemaphore.await();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
    /** 
     * 關閉ZK連接 
     */  
    public void releaseConnection() {  
        if (this.zk != null) {  
            try {  
                this.zk.close();  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * 創建節點 
     * @param path 節點路徑 
     * @param data 數據內容 
     * @return  
     */  
    public boolean createPath(String path, String data) {  
        try {  
            //設置監控(由於zookeeper的監控都是一次性的所以 每次必須設置監控)  
            this.zk.exists(path, true);  
            System.out.println(LOG_PREFIX_OF_MAIN + "節點創建成功, Path: " +   
                               this.zk.create(  /**路徑*/   
                                                path,   
                                                /**數據*/  
                                                data.getBytes(),   
                                                /**所有可見*/  
                                                Ids.OPEN_ACL_UNSAFE,   
                                                /**永久存儲*/  
                                                CreateMode.PERSISTENT ) +     
                               ", content: " + data);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
        return true;  
    }  
  
    /** 
     * 讀取指定節點數據內容 
     * @param path 節點路徑 
     * @return 
     */  
    public String readData(String path, boolean needWatch) {  
        try {  
            return new String(this.zk.getData(path, needWatch, null));  
        } catch (Exception e) {  
            e.printStackTrace();  
            return "";  
        }  
    }  
  
    /** 
     * 更新指定節點數據內容 
     * @param path 節點路徑 
     * @param data 數據內容 
     * @return 
     */  
    public boolean writeData(String path, String data) {  
        try {  
            System.out.println(LOG_PREFIX_OF_MAIN + "更新數據成功,path:" + path + ", stat: " +  
                                this.zk.setData(path, data.getBytes(), -1));  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return false;  
    }  
  
    /** 
     * 刪除指定節點 
     *  
     * @param path 
     *            節點path 
     */  
    public void deleteNode(String path) {  
        try {  
            this.zk.delete(path, -1);  
            System.out.println(LOG_PREFIX_OF_MAIN + "刪除節點成功,path:" + path);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
    /** 
     * 判斷指定節點是否存在 
     * @param path 節點路徑 
     */  
    public Stat exists(String path, boolean needWatch) {  
        try {  
            return this.zk.exists(path, needWatch);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
  
    /** 
     * 獲取子節點 
     * @param path 節點路徑 
     */  
    private List<String> getChildren(String path, boolean needWatch) {  
        try {  
            return this.zk.getChildren(path, needWatch);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
  
    /** 
     * 刪除所有節點 
     */  
    public void deleteAllTestPath() {  
        if(this.exists(CHILDREN_PATH, false) != null){  
            this.deleteNode(CHILDREN_PATH);  
        }  
        if(this.exists(PARENT_PATH, false) != null){  
            this.deleteNode(PARENT_PATH);  
        }         
    }  
      
    /** 
     * 收到來自Server的Watcher通知後的處理。 
     */  
    @Override  
    public void process(WatchedEvent event) {  
          
        System.out.println("進入 process 。。。。。event = " + event);  
          
        try {  
            Thread.sleep(200);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
          
        if (event == null) {  
            return;  
        }  
          
        // 連接狀態  
        KeeperState keeperState = event.getState();  
        // 事件類型  
        EventType eventType = event.getType();  
        // 受影響的path  
        String path = event.getPath();  
          
        String logPrefix = "【Watcher-" + this.seq.incrementAndGet() + "】";  
  
        System.out.println(logPrefix + "收到Watcher通知");  
        System.out.println(logPrefix + "連接狀態:\t" + keeperState.toString());  
        System.out.println(logPrefix + "事件類型:\t" + eventType.toString());  
  
        if (KeeperState.SyncConnected == keeperState) {  
            // 成功連接上ZK服務器  
            if (EventType.None == eventType) {  
                System.out.println(logPrefix + "成功連接上ZK服務器");  
                connectedSemaphore.countDown();  
            }   
            //創建節點  
            else if (EventType.NodeCreated == eventType) {  
                System.out.println(logPrefix + "節點創建");  
                try {  
                    Thread.sleep(100);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
                this.exists(path, true);  
            }   
            //更新節點  
            else if (EventType.NodeDataChanged == eventType) {  
                System.out.println(logPrefix + "節點數據更新");  
                System.out.println("我看看走不走這裏........");  
                try {  
                    Thread.sleep(100);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
                System.out.println(logPrefix + "數據內容: " + this.readData(PARENT_PATH, true));  
            }   
            //更新子節點  
            else if (EventType.NodeChildrenChanged == eventType) {  
                System.out.println(logPrefix + "子節點變更");  
                try {  
                    Thread.sleep(3000);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
                System.out.println(logPrefix + "子節點列表:" + this.getChildren(PARENT_PATH, true));  
            }   
            //刪除節點  
            else if (EventType.NodeDeleted == eventType) {  
                System.out.println(logPrefix + "節點 " + path + " 被刪除");  
            }  
            else ;  
        }   
        else if (KeeperState.Disconnected == keeperState) {  
            System.out.println(logPrefix + "與ZK服務器斷開連接");  
        }   
        else if (KeeperState.AuthFailed == keeperState) {  
            System.out.println(logPrefix + "權限檢查失敗");  
        }   
        else if (KeeperState.Expired == keeperState) {  
            System.out.println(logPrefix + "會話失效");  
        }  
        else ;  
  
        System.out.println("--------------------------------------------");  
  
    }
    
    /** 
      * <B>方法名稱:</B>測試zookeeper監控<BR> 
      * <B>概要說明:</B>主要測試watch功能<BR> 
      * @param args 
      * @throws Exception 
      */  
     public static void main(String[] args) throws Exception {  
    
         //建立watcher  
         ZooKeeperWatcher zkWatch = new ZooKeeperWatcher();  
         //創建連接  
         zkWatch.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);  
         //System.out.println(zkWatch.zk.toString());  
           
         Thread.sleep(1000);  
           
         // 清理節點  
         zkWatch.deleteAllTestPath();  
           
         if (zkWatch.createPath(PARENT_PATH, System.currentTimeMillis() + "")) {  
               
             Thread.sleep(1000);  
               
               
             // 讀取數據,在操作節點數據之前先調用zookeeper的getData()方法是爲了可以watch到對節點的操作。watch是一次性的,  
             // 也就是說,如果第二次又重新調用了setData()方法,在此之前需要重新調用一次。  
             System.out.println("---------------------- read parent ----------------------------");  
             //zkWatch.readData(PARENT_PATH, true);  
               
             /** 讀取子節點,設置對子節點變化的watch,如果不寫該方法,則在創建子節點是隻會輸出NodeCreated,而不會輸出NodeChildrenChanged, 
                 也就是說創建子節點時沒有watch。 
                 如果是遞歸的創建子節點,如path="/p/c1/c2"的話,getChildren(PARENT_PATH, ture)只會在創建c1時watch,輸出c1的NodeChildrenChanged, 
                 而不會輸出創建c2時的NodeChildrenChanged,如果watch到c2的NodeChildrenChanged,則需要再調用一次getChildren(String path, true)方法, 
                 其中path="/p/c1" 
             */  
             System.out.println("---------------------- read children path ----------------------------");  
             zkWatch.getChildren(PARENT_PATH, true);  
    
             // 更新數據  
             zkWatch.writeData(PARENT_PATH, System.currentTimeMillis() + "");  
               
             Thread.sleep(1000);  
               
             // 創建子節點,同理如果想要watch到NodeChildrenChanged狀態,需要調用getChildren(CHILDREN_PATH, true)  
             zkWatch.readData(CHILDREN_PATH, true);  
             zkWatch.createPath(CHILDREN_PATH, System.currentTimeMillis() + "");  
               
             Thread.sleep(1000);  
               
             zkWatch.writeData(CHILDREN_PATH, System.currentTimeMillis() + "");  
         }  
           
         Thread.sleep(50000);  
         // 清理節點  
         zkWatch.deleteAllTestPath();  
         Thread.sleep(1000);  
         zkWatch.releaseConnection();  
     }          
}

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

    public class ZookeeperAuth implements Watcher {  
      
        /** 連接地址 */  
        final static String CONNECT_ADDR = "192.168.159.129:2181,192.168.159.130:2181,192.168.159.131:2181,192.168.159.132:2181,192.168.159.133:2181";  
        /** 測試路徑 */  
        final static String PATH = "/testAuth";  
        final static String PATH_DEL = "/testAuth/delNode";  
        /** 認證類型 */  
        final static String authentication_type = "digest";  
        /** 認證正確方法 */  
        final static String correctAuthentication = "123456";  
        /** 認證錯誤方法 */  
        final static String badAuthentication = "654321";  
          
        static ZooKeeper zk = null;  
        /** 計時器 */  
        AtomicInteger seq = new AtomicInteger();  
        /** 標識 */  
        private static final String LOG_PREFIX_OF_MAIN = "【Main】";  
          
        private CountDownLatch connectedSemaphore = new CountDownLatch(1);  
          
        @Override  
        public void process(WatchedEvent event) {  
            try {  
                Thread.sleep(200);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            if (event==null) {  
                return;  
            }  
            // 連接狀態  
            KeeperState keeperState = event.getState();  
            // 事件類型  
            EventType eventType = event.getType();  
            // 受影響的path  
            String path = event.getPath();  
              
            String logPrefix = "【Watcher-" + this.seq.incrementAndGet() + "】";  
      
            System.out.println(logPrefix + "收到Watcher通知");  
            System.out.println(logPrefix + "連接狀態:\t" + keeperState.toString());  
            System.out.println(logPrefix + "事件類型:\t" + eventType.toString());  
            if (KeeperState.SyncConnected == keeperState) {  
                // 成功連接上ZK服務器  
                if (EventType.None == eventType) {  
                    System.out.println(logPrefix + "成功連接上ZK服務器");  
                    connectedSemaphore.countDown();  
                }   
            } else if (KeeperState.Disconnected == keeperState) {  
                System.out.println(logPrefix + "與ZK服務器斷開連接");  
            } else if (KeeperState.AuthFailed == keeperState) {  
                System.out.println(logPrefix + "權限檢查失敗");  
            } else if (KeeperState.Expired == keeperState) {  
                System.out.println(logPrefix + "會話失效");  
            }  
            System.out.println("--------------------------------------------");  
        }  
        /** 
         * 創建ZK連接 
         *  
         * @param connectString 
         *            ZK服務器地址列表 
         * @param sessionTimeout 
         *            Session超時時間 
         */  
        public void createConnection(String connectString, int sessionTimeout) {  
            this.releaseConnection();  
            try {  
                zk = new ZooKeeper(connectString, sessionTimeout, this);  
                //添加節點授權  
                zk.addAuthInfo(authentication_type,correctAuthentication.getBytes());  
                System.out.println(LOG_PREFIX_OF_MAIN + "開始連接ZK服務器");  
                //倒數等待  
                connectedSemaphore.await();  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        /** 
         * 關閉ZK連接 
         */  
        public void releaseConnection() {  
            if (this.zk!=null) {  
                try {  
                    this.zk.close();  
                } catch (InterruptedException e) {  
                }  
            }  
        }  
          
        /** 
         *  
         * <B>方法名稱:</B>測試函數<BR> 
         * <B>概要說明:</B>測試認證<BR> 
         * @param args 
         * @throws Exception 
         */  
        public static void main(String[] args) throws Exception {  
              
            ZookeeperAuth testAuth = new ZookeeperAuth();  
            testAuth.createConnection(CONNECT_ADDR,2000);  
            List<ACL> acls = new ArrayList<ACL>(1);  
            for (ACL ids_acl : Ids.CREATOR_ALL_ACL) {  
                acls.add(ids_acl);  
            }  
      
            try {  
                zk.create(PATH, "init content".getBytes(), acls, CreateMode.PERSISTENT);  
                System.out.println("使用授權key:" + correctAuthentication + "創建節點:"+ PATH + ", 初始內容是: init content");  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
            try {  
                zk.create(PATH_DEL, "will be deleted! ".getBytes(), acls, CreateMode.PERSISTENT);  
                System.out.println("使用授權key:" + correctAuthentication + "創建節點:"+ PATH_DEL + ", 初始內容是: init content");  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
      
            // 獲取數據  
            getDataByNoAuthentication();  
            getDataByBadAuthentication();  
            getDataByCorrectAuthentication();  
      
            // 更新數據  
            updateDataByNoAuthentication();  
            updateDataByBadAuthentication();  
            updateDataByCorrectAuthentication();  
      
            // 刪除數據  
            deleteNodeByBadAuthentication();  
            deleteNodeByNoAuthentication();  
            deleteNodeByCorrectAuthentication();  
            //  
            Thread.sleep(1000);  
              
            deleteParent();  
            //釋放連接  
            testAuth.releaseConnection();  
        }  
        /** 獲取數據:採用錯誤的密碼 */  
        static void getDataByBadAuthentication() {  
            String prefix = "[使用錯誤的授權信息]";  
            try {  
                ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null);  
                //授權  
                badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());  
                Thread.sleep(2000);  
                System.out.println(prefix + "獲取數據:" + PATH);  
                System.out.println(prefix + "成功獲取數據:" + badzk.getData(PATH, false, null));  
            } catch (Exception e) {  
                System.err.println(prefix + "獲取數據失敗,原因:" + e.getMessage());  
            }  
        }  
      
        /** 獲取數據:不採用密碼 */  
        static void getDataByNoAuthentication() {  
            String prefix = "[不使用任何授權信息]";  
            try {  
                System.out.println(prefix + "獲取數據:" + PATH);  
                ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null);  
                Thread.sleep(2000);  
                System.out.println(prefix + "成功獲取數據:" + nozk.getData(PATH, false, null));  
            } catch (Exception e) {  
                System.err.println(prefix + "獲取數據失敗,原因:" + e.getMessage());  
            }  
        }  
      
        /** 採用正確的密碼 */  
        static void getDataByCorrectAuthentication() {  
            String prefix = "[使用正確的授權信息]";  
            try {  
                System.out.println(prefix + "獲取數據:" + PATH);  
                  
                System.out.println(prefix + "成功獲取數據:" + zk.getData(PATH, false, null));  
            } catch (Exception e) {  
                System.out.println(prefix + "獲取數據失敗,原因:" + e.getMessage());  
            }  
        }  
      
        /** 
         * 更新數據:不採用密碼 
         */  
        static void updateDataByNoAuthentication() {  
      
            String prefix = "[不使用任何授權信息]";  
      
            System.out.println(prefix + "更新數據: " + PATH);  
            try {  
                ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null);  
                Thread.sleep(2000);  
                Stat stat = nozk.exists(PATH, false);  
                if (stat!=null) {  
                    nozk.setData(PATH, prefix.getBytes(), -1);  
                    System.out.println(prefix + "更新成功");  
                }  
            } catch (Exception e) {  
                System.err.println(prefix + "更新失敗,原因是:" + e.getMessage());  
            }  
        }  
      
        /** 
         * 更新數據:採用錯誤的密碼 
         */  
        static void updateDataByBadAuthentication() {  
      
            String prefix = "[使用錯誤的授權信息]";  
      
            System.out.println(prefix + "更新數據:" + PATH);  
            try {  
                ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null);  
                //授權  
                badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());  
                Thread.sleep(2000);  
                Stat stat = badzk.exists(PATH, false);  
                if (stat!=null) {  
                    badzk.setData(PATH, prefix.getBytes(), -1);  
                    System.out.println(prefix + "更新成功");  
                }  
            } catch (Exception e) {  
                System.err.println(prefix + "更新失敗,原因是:" + e.getMessage());  
            }  
        }  
      
        /** 
         * 更新數據:採用正確的密碼 
         */  
        static void updateDataByCorrectAuthentication() {  
      
            String prefix = "[使用正確的授權信息]";  
      
            System.out.println(prefix + "更新數據:" + PATH);  
            try {  
                Stat stat = zk.exists(PATH, false);  
                if (stat!=null) {  
                    zk.setData(PATH, prefix.getBytes(), -1);  
                    System.out.println(prefix + "更新成功");  
                }  
            } catch (Exception e) {  
                System.err.println(prefix + "更新失敗,原因是:" + e.getMessage());  
            }  
        }  
      
        /** 
         * 不使用密碼 刪除節點 
         */  
        static void deleteNodeByNoAuthentication() throws Exception {  
      
            String prefix = "[不使用任何授權信息]";  
      
            try {  
                System.out.println(prefix + "刪除節點:" + PATH_DEL);  
                ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null);  
                Thread.sleep(2000);  
                Stat stat = nozk.exists(PATH_DEL, false);  
                if (stat!=null) {  
                    nozk.delete(PATH_DEL,-1);  
                    System.out.println(prefix + "刪除成功");  
                }  
            } catch (Exception e) {  
                System.err.println(prefix + "刪除失敗,原因是:" + e.getMessage());  
            }  
        }  
      
        /** 
         * 採用錯誤的密碼刪除節點 
         */  
        static void deleteNodeByBadAuthentication() throws Exception {  
      
            String prefix = "[使用錯誤的授權信息]";  
      
            try {  
                System.out.println(prefix + "刪除節點:" + PATH_DEL);  
                ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null);  
                //授權  
                badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());  
                Thread.sleep(2000);  
                Stat stat = badzk.exists(PATH_DEL, false);  
                if (stat!=null) {  
                    badzk.delete(PATH_DEL, -1);  
                    System.out.println(prefix + "刪除成功");  
                }  
            } catch (Exception e) {  
                System.err.println(prefix + "刪除失敗,原因是:" + e.getMessage());  
            }  
        }  
      
        /** 
         * 使用正確的密碼刪除節點 
         */  
        static void deleteNodeByCorrectAuthentication() throws Exception {  
      
            String prefix = "[使用正確的授權信息]";  
      
            try {  
                System.out.println(prefix + "刪除節點:" + PATH_DEL);  
                Stat stat = zk.exists(PATH_DEL, false);  
                if (stat!=null) {  
                    zk.delete(PATH_DEL, -1);  
                    System.out.println(prefix + "刪除成功");  
                }  
            } catch (Exception e) {  
                System.out.println(prefix + "刪除失敗,原因是:" + e.getMessage());  
            }  
        }  
      
        /** 
         * 使用正確的密碼刪除節點 
         */  
        static void deleteParent() throws Exception {  
            try {  
                Stat stat = zk.exists(PATH_DEL, false);  
                if (stat == null) {  
                    zk.delete(PATH, -1);  
                }  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
      
    }  

轉自:隔壁老王的專欄  https://blog.csdn.net/haoyuyang/article/details/53436625


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章