一、安裝jdk
首先zookeeper是java編寫的,需要安裝jdk,方法有3種,(以下操作來自:http://www.linuxidc.com/Linux/2016-09/134941.htm)
方法一:手動解壓JDK的壓縮包,然後設置環境變量
1.在/usr/目錄下創建java目錄
[root@localhost ~]# mkdir/usr/java
[root@localhost ~]# cd /usr/java
2.下載jdk,然後解壓
[root@localhost java]# curl -O http://download.Oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz
[root@localhost java]# tar -zxvf jdk-7u79-linux-x64.tar.gz
3.設置環境變量
[root@localhost java]# vi /etc/profile
在profile中添加如下內容:
#set java environment
JAVA_HOME=/usr/java/jdk1.7.0_79
JRE_HOME=/usr/java/jdk1.7.0_79/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
讓修改生效:
[root@localhost java]# source /etc/profile
4.驗證JDK有效性
[root@localhost java]# java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
方法二:用yum安裝JDK
1.查看yum庫中都有哪些jdk版本(暫時只發現了openjdk)
[root@localhost ~]# yum search java|grep jdk
ldapjdk-javadoc.x86_64 : Javadoc for ldapjdk
java-1.6.0-openjdk.x86_64 : OpenJDK Runtime Environment
java-1.6.0-openjdk-demo.x86_64 : OpenJDK Demos
java-1.6.0-openjdk-devel.x86_64 : OpenJDK Development Environment
java-1.6.0-openjdk-javadoc.x86_64 : OpenJDK API Documentation
java-1.6.0-openjdk-src.x86_64 : OpenJDK Source Bundle
java-1.7.0-openjdk.x86_64 : OpenJDK Runtime Environment
java-1.7.0-openjdk-demo.x86_64 : OpenJDK Demos
java-1.7.0-openjdk-devel.x86_64 : OpenJDK Development Environment
java-1.7.0-openjdk-javadoc.noarch : OpenJDK API Documentation
java-1.7.0-openjdk-src.x86_64 : OpenJDK Source Bundle
java-1.8.0-openjdk.x86_64 : OpenJDK Runtime Environment
java-1.8.0-openjdk-demo.x86_64 : OpenJDK Demos
java-1.8.0-openjdk-devel.x86_64 : OpenJDK Development Environment
java-1.8.0-openjdk-headless.x86_64 : OpenJDK Runtime Environment
java-1.8.0-openjdk-javadoc.noarch : OpenJDK API Documentation
java-1.8.0-openjdk-src.x86_64 : OpenJDK Source Bundle
ldapjdk.x86_64 : The Mozilla LDAP Java SDK
2.選擇版本,進行安裝
//選擇1.7版本進行安裝
[root@localhost ~]# yum install java-1.7.0-openjdk
//安裝完之後,默認的安裝目錄是在: /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.75.x86_64
3.設置環境變量
[root@localhost ~]# vi /etc/profile
在profile文件中添加如下內容
#set java environment
JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.75.x86_64
JRE_HOME=$JAVA_HOME/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
讓修改生效
[root@localhost java]# source /etc/profile
4.驗證(同上一方法)
方法三:用rpm安裝JDK
1.下載rpm安裝文件
[root@localhost ~]$ curl -O http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.rpm
2.使用rpm命令安裝
[root@localhost ~]# rpm -ivh jdk-7u79-linux-x64.rpm
3.設置環境變量
[root@localhost java]# vi /etc/profile
在打開的profile文件中添加如下內容
#set java environment
JAVA_HOME=/usr/java/jdk1.7.0_79
JRE_HOME=/usr/java/jdk1.7.0_79/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
讓修改生效
[root@localhost java]# source /etc/profile
4.驗證(同上一方法)
注:和yum安裝類似,不用設置環境變量就可以運行java命令。rpm安裝方式默認會把jdk安裝到/usr/java/jdk1.7.0_79,然後通過三層鏈接,鏈接到/usr/bin,具體鏈接如下:
[root@localhost ~]# cd /bin
[root@localhost bin]# ll|grep java
lrwxrwxrwx. 1 root root 25 Mar 28 11:24 jar ->/usr/java/default/bin/jar
lrwxrwxrwx. 1 root root 26 Mar 28 11:24 java -> /usr/java/default/bin/java
lrwxrwxrwx. 1 root root 27 Mar 28 11:24 javac ->/usr/java/default/bin/javac
lrwxrwxrwx. 1 root root 29 Mar 28 11:24 javadoc ->/usr/java/default/bin/javadoc
lrwxrwxrwx. 1 root root 28 Mar 28 11:24 javaws ->/usr/java/default/bin/javaws
lrwxrwxrwx. 1 root root 30 Mar 28 11:24 jcontrol ->/usr/java/default/bin/jcontrol
[root@localhost bin]# cd /usr/java/
[root@localhost java]# ll
total 4
lrwxrwxrwx. 1 root root 16 Mar 28 11:24 default-> /usr/java/latest
drwxr-xr-x. 8 root root 4096 Mar 28 11:24 jdk1.7.0_79
lrwxrwxrwx. 1 root root 21 Mar 28 11:24 latest -> /usr/java/jdk1.7.0_79
方法四:Ubuntu 上使用apt-get安裝JDK
1.查看apt庫都有哪些jdk版本
root@linuxidc:~# apt-cache search java|grep jdk
default-jdk - Standard Java or Java compatible Development Kit
default-jdk-doc - Standard Java or Java compatible Development Kit (documentation)
gcj-4.6-jdk - gcj and classpath development tools for Java(TM)
gcj-jdk - gcj and classpath development tools for Java(TM)
openjdk-6-dbg - Java runtime based on OpenJDK (debugging symbols)
openjdk-6-demo - Java runtime based on OpenJDK (demos and examples)
openjdk-6-doc - OpenJDK Development Kit (JDK) documentation
openjdk-6-jdk - OpenJDK Development Kit (JDK)
openjdk-6-jre-lib - OpenJDK Java runtime (architecture independent libraries)
openjdk-6-source - OpenJDK Development Kit (JDK) source files
openjdk-7-dbg - Java runtime based on OpenJDK (debugging symbols)
openjdk-7-demo - Java runtime based on OpenJDK (demos and examples)
openjdk-7-doc - OpenJDK Development Kit (JDK) documentation
openjdk-7-jdk - OpenJDK Development Kit (JDK)
openjdk-7-source - OpenJDK Development Kit (JDK) source files
uwsgi-plugin-jvm-openjdk-6 - Java plugin for uWSGI (OpenJDK 6)
uwsgi-plugin-jwsgi-openjdk-6 - JWSGI plugin for uWSGI (OpenJDK 6)
openjdk-6-jre - OpenJDK Java runtime, using Hotspot JIT
openjdk-6-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless)
openjdk-7-jre - OpenJDK Java runtime, using Hotspot JIT
openjdk-7-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless)
openjdk-7-jre-lib - OpenJDK Java runtime (architecture independent libraries)
2.選擇版本進行安裝
root@linuxidc:~# apt-get install openjdk-7-jdk
3.設置環境變量
root@linuxidc:~# vi /etc/profile
在打開的profile文件中添加如下內容
#set java environment
JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
JRE_HOME=$JAVA_HOME/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
讓修改生效
root@linuxidc:~# source /etc/profile
4.驗證(同上一方法)
二、安裝zookeeper
zookeeper有3種使用方法:集羣模式、僞集羣模式、單機模式。以下以僞集羣模式爲例(來自:http://blog.csdn.net/catoop/article/details/50848555)
集羣部署
1. 下載
官網:http://zookeeper.apache.org/releases.html
下載:zookeeper-3.4.8.tar.gz
2. 安裝
因爲資源有限,所以我在同一個服務器上面創建3個目錄 server1、server2、server3 來模擬3臺服務器集羣。
cd server1
tar -zxvf zookeeper-3.4.8.tar.gz
mkdir data
mkdir dataLog
data 爲數據目錄,dataLog 爲日誌目錄。
3. 配置
cd zookeeper-3.4.8/conf
創建文件 zoo.cfg,內容如下:
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/opt/zookeeper/server1/data
dataLogDir=/opt/zookeeper/server1/dataLog
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
tickTime:zookeeper中使用的基本時間單位, 毫秒值。
initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這裏所說的客戶端不是用戶連接 Zookeeper 服務器的客戶端,而是 Zookeeper 服務器集羣中連接到 Leader 的 Follower 服務器)初始化連接時最長能忍受多少個 tickTime 時間間隔數。這裏設置爲5表名最長容忍時間爲 5 * 2000 = 10 秒。
syncLimit:這個配置標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2 * 2000 = 4 秒。
dataDir 和 dataLogDir 看配置就知道幹嗎的了,不用解釋。
clientPort:監聽client連接的端口號,這裏說的client就是連接到Zookeeper的代碼程序。
server.{myid}={ip}:{leader服務器交換信息的端口}:{當leader服務器掛了後, 選舉leader的端口}
maxClientCnxns:對於一個客戶端的連接數限制,默認是60,這在大部分時候是足夠了。但是在我們實際使用中發現,在測試環境經常超過這個數,經過調查發現有的團隊將幾十個應用全部部署到一臺機器上,以方便測試,於是這個數字就超過了。
修改zoo.cfg非常簡單,然後還需要創建myid文件:
cd server1/data
echo 1 > myid
然後拷貝server1爲server2和server3,並修改其中的zoo.cfg配置,當然也要修改myid的內容爲2和3。
下面給出3個server的zoo.cfg 內容:
# server1
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/opt/zookeeper/server1/data
dataLogDir=/opt/zookeeper/server1/dataLog
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
# server2
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/opt/zookeeper/server2/data
dataLogDir=/opt/zookeeper/server2/dataLog
clientPort=2182
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
# server3
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/opt/zookeeper/server3/data
dataLogDir=/opt/zookeeper/server3/dataLog
clientPort=2183
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
這裏做下說明:因爲我們是在同一個機器上模擬的集羣,所以要注意server端口號和clientPort不要重複了,不然會出現端口衝突。所以,如果我們是3個不同的機器上做的3個server,那麼我們的zoo.cfg配置都是一樣的(注意server.{myid}=後面的IP地址使用具體的IP地址,如192.168.0.88)。還有就是,每一個server的myid內容都不能一樣,這也可以理解爲不同server的標識。
4. 啓動
進入 zookeeper-3.4.8/bin 目錄,使用 ./zkServer.sh start 啓動zk服務。(你也可以使用 ./zkServer.sh start myzoo.cfg 指定配置文件啓動,這在自動化運維的時候很有用)
使用 tail -f zookeeper.out 查看日誌。
要說的是:在啓動第一個的時候,日誌中會出現一堆錯誤,仔細一看就能明白,是因爲另外2個server還沒有啓動它連接不上的錯誤。然後當我們啓動第二個server的時候,日誌中的錯誤將會減少。最後我們把所有server都啓動起來後,日誌中便沒有錯誤了。
5. 測試
隨便進入一個zk目錄,連接一個server測試。
cd zookeeper-3.4.8/bin
./zkCli.sh -server 127.0.0.1:2181
如果你要連接別的服務器,請指定具體的IP地址。
幾個基本命令說明:
ls 查看指定節點中包含的子節點(如:ls / 或 ls /app1/server1)
create 創建節點並賦值
get 讀取節點內容
set 改變節點內容
delete 刪除節點
注意zk中所有節點都基於路徑確定,如你要刪除 /app1/server1/nodeA 的命令爲:
delete /app1/server1/nodeA
下面是基本操作截圖:
Java程序Demo
創建一個Maven工程
打開pom.xml文件添加zookeeper依賴
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
創建Demo.java,代碼如下:
package com.shanhy.demo.zookeeper;
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
/**
* Zookeeper測試
*
* @create 2016年3月10日
*/
public class Test {
// 會話超時時間,設置爲與系統默認時間一致
private static final int SESSION_TIMEOUT = 30 * 1000;
// 創建 ZooKeeper 實例
private ZooKeeper zk;
// 創建 Watcher 實例
private Watcher wh = new Watcher() {
/**
* Watched事件
*/
public void process(WatchedEvent event) {
System.out.println("WatchedEvent >>> " + event.toString());
}
};
// 初始化 ZooKeeper 實例
private void createZKInstance() throws IOException {
// 連接到ZK服務,多個可以用逗號分割寫
zk = new ZooKeeper("192.168.19.130:2181,192.168.19.130:2182,192.168.19.130:2183", Test.SESSION_TIMEOUT, this.wh);
}
private void ZKOperations() throws IOException, InterruptedException, KeeperException {
System.out.println("\n1. 創建 ZooKeeper 節點 (znode : zoo2, 數據: myData2 ,權限: OPEN_ACL_UNSAFE ,節點類型: Persistent");
zk.create("/zoo2", "myData2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("\n2. 查看是否創建成功: ");
System.out.println(new String(zk.getData("/zoo2", this.wh, null)));// 添加Watch
// 前面一行我們添加了對/zoo2節點的監視,所以這裏對/zoo2進行修改的時候,會觸發Watch事件。
System.out.println("\n3. 修改節點數據 ");
zk.setData("/zoo2", "shanhy20160310".getBytes(), -1);
// 這裏再次進行修改,則不會觸發Watch事件,這就是我們驗證ZK的一個特性“一次性觸發”,也就是說設置一次監視,只會對下次操作起一次作用。
System.out.println("\n3-1. 再次修改節點數據 ");
zk.setData("/zoo2", "shanhy20160310-ABCD".getBytes(), -1);
System.out.println("\n4. 查看是否修改成功: ");
System.out.println(new String(zk.getData("/zoo2", false, null)));
System.out.println("\n5. 刪除節點 ");
zk.delete("/zoo2", -1);
System.out.println("\n6. 查看節點是否被刪除: ");
System.out.println(" 節點狀態: [" + zk.exists("/zoo2", false) + "]");
}
private void ZKClose() throws InterruptedException {
zk.close();
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
Test dm = new Test();
dm.createZKInstance();
dm.ZKOperations();
dm.ZKClose();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
我想代碼不用解釋了,該註釋的裏面都註釋了。
下面有一種特殊的情況的處理思路:
有server1、server2、server3這三個服務,在client去連接zk的時候,指向server1初始化的過程中是沒有問題的,然而剛剛初始化完成,準備去連接server1的時候,server1因爲網絡等原因掛掉了。
然而對client來說,它會拿server1的配置去請求連接,這時肯定會報連接被拒絕的異常以致啓動退出。
所以優雅的解決這個問題的方法思路就是“在連接的時候判斷連接狀態,如果未連接成功,程序自動使用其他連接去請求連接”,這樣來避開這種罕見的異常問題。
代碼如下:
// 初始化 ZooKeeper 實例
private void createZKInstance() throws IOException {
// 連接到ZK服務,多個可以用逗號分割寫
zk = new ZooKeeper("192.168.19.130:2181,192.168.19.130:2182,192.168.19.130:2183", Test.SESSION_TIMEOUT, this.wh);
if(!zk.getState().equals(States.CONNECTED)){
while(true){
if(zk.getState().equals(States.CONNECTED)){
break;
}
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
上面的代碼是基於zk提供的庫的API來你使用的,爲了更易於使用,有人寫了開源的zkclient,我們可以直接使用它來操作zk。
zkclient 開源地址:https://github.com/sgroschupf/zkclient
maven 依賴配置:
<!--zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.7</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
zkClient 針對 zk 的一次性watcher,做了重新封裝,然後定義了 stateChanged、znodeChanged、dataChanged 三種監聽器。
- 監聽children變化
- 監聽節點數據變化
- 監聽連接狀態變化
代碼如下:
package com.shanhy.demo.zookeeper;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.I0Itec.zkclient.DataUpdater;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.IZkStateListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.Watcher.Event.KeeperState;
/**
* ZkClient的使用測試
*
* @author 單紅宇(365384722)
* @myblog http://blog.csdn.net/catoop/
* @create 2016年3月11日
*/
public class ZkClientTest {
public static void main(String[] args) {
ZkClient zkClient = new ZkClient("192.168.19.130:2181,192.168.19.130:2182,192.168.19.130:2183");
String node = "/myapp";
// 訂閱監聽事件
childChangesListener(zkClient, node);
dataChangesListener(zkClient, node);
stateChangesListener(zkClient);
if (!zkClient.exists(node)) {
zkClient.createPersistent(node, "hello zookeeper");
}
System.out.println(zkClient.readData(node));
zkClient.updateDataSerialized(node, new DataUpdater<String>() {
public String update(String currentData) {
return currentData + "-123";
}
});
System.out.println(zkClient.readData(node));
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 訂閱children變化
*
* @param zkClient
* @param path
* @author SHANHY
* @create 2016年3月11日
*/
public static void childChangesListener(ZkClient zkClient, final String path) {
zkClient.subscribeChildChanges(path, new IZkChildListener() {
public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
System.out.println("clildren of path " + parentPath + ":" + currentChilds);
}
});
}
/**
* 訂閱節點數據變化
*
* @param zkClient
* @param path
* @author SHANHY
* @create 2016年3月11日
*/
public static void dataChangesListener(ZkClient zkClient, final String path){
zkClient.subscribeDataChanges(path, new IZkDataListener(){
public void handleDataChange(String dataPath, Object data) throws Exception {
System.out.println("Data of " + dataPath + " has changed.");
}
public void handleDataDeleted(String dataPath) throws Exception {
System.out.println("Data of " + dataPath + " has changed.");
}
});
}
/**
* 訂閱狀態變化
*
* @param zkClient
* @author SHANHY
* @create 2016年3月11日
*/
public static void stateChangesListener(ZkClient zkClient){
zkClient.subscribeStateChanges(new IZkStateListener() {
public void handleStateChanged(KeeperState state) throws Exception {
System.out.println("handleStateChanged");
}
public void handleSessionEstablishmentError(Throwable error) throws Exception {
System.out.println("handleSessionEstablishmentError");
}
public void handleNewSession() throws Exception {
System.out.println("handleNewSession");
}
});
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
ZkClient 做了便捷的包裝,對Watch做了增強處理。
subscribeChildChanges實際上是通過exists和getChildren關注了兩個事件。這樣當create(“/path”)時,對應path上通過getChildren註冊的listener也會被調用。另外subscribeDataChanges實際上只是通過exists註冊了事件。因爲從上表可以看到,對於一個更新,通過exists和getData註冊的watcher要麼都會觸發,要麼都不會觸發。
關於session超時的問題,ZkClient 貌似還是有對 Session Expired 處理的,在ZkClient.processStateChanged方法中。雖然能重新連接,但是連接上是一個新的 session,原有創建的ephemeral znode和watch會被刪除,程序上你可能需要處理這個問題。
最後說幾點關於ZkClient的注意事項:
1. 創建節點的時候一定要先判斷節點是否存在,如果直接使用zkclient創建一個已經存在的節點,則會拋出異常。
2. 使用zkclient創建節點的時候,path描述的路徑,預新增的最終節點之前的所有父節點都必須要存在,否則會拋出異常。所以根據自己需要做好處理。