Zookeeper常見錯誤筆記


http://www.bubuko.com/infodetail-615044.html

 

時間: 2015-02-03 16:40:33      閱讀:859      評論:0      收藏:0      [點我收藏+]

標簽:class   style   代碼   com   log   使用   java   文件   http   

Zookeeper開發過程中一些常見問題

一、 關於zookeeper_init函數的使用

問題描述:

開發人員在調用zookeeper_init函數時,若返回一個非空句柄zhandle_t  *zh,則認為初始化成功,這樣可能會導致后續操作失敗。

問題分析:

zhandle_t  *zookeeper_init(const char *host, watcher_fn fn, int recv_timeout,const   clientid_t *clientid, void *context, int flags) 函 數     返回一個zookeeper客戶端與服務器通信的句柄,通常我們僅僅根據返回句柄情況來判斷zookeeper 客戶端與zookeeper服務器是否 建立連接。如果句柄為空則認為是失敗,非空則成功。其實不然,zookeeper_init創建與ZooKeeper服務端通信的句柄以及對應於此句柄的會話,而會話的創建是一個異步的過程,僅當會話建立成功,zookeeper_init才返回一個可用句柄。

問題解決:

如何正確判斷zookeepr_init初始化成功,可通過以下三種方式
1、判斷句柄的state是否為ZOO_CONNECTED_STATE狀態,通過zoo_state(zh)判斷狀態值是否為ZOO_CONNECTED_STATE。

 

 

2、 在zookeeper_init中設置watcher,當zookeeper client與server會話建立后,觸發watcher,當 watcher 的state = 3 (ZOO_CONNECTED_STATE), type = -1(ZOO_SESSION_EVENT)時,確認 會話成功建立,此時zookeeper client 初始化成功,可進行后續操作。
3、業務上可以做保證,調用zookeeper_init返回句柄zh,通過該句柄嘗試做zoo_exists()或zoo_get_data()等操作,根據操作結果來判斷是否初始化成功。

 

二、 如何解決session失效問題

問題描述:

session失效,導致注冊的watcher全部丟失。

問題分析:

如果zookeeper client與server在協商的超時時間內仍沒有建立連接,當client與server再次建立連接時,由於session失效了,所有watcher已經被服務器端刪除,從而導致所有的watcher需要重新注冊。
session 失效,zookeeper client與server重連后所有watcher都會收到兩次觸發,第一次 wathetr state = 1,type = -1(state = 1表示正在連接中,type = -1 表示session事件);第二次 watcher state = -112,type = -1(state = -112表示session失效)。

問題解決:

可以通過以下兩種方法解決session失效問題
1、獲取觸發session失效watcher后,業務重新注冊所有的watcher。
2、不能根本解決,但是可以減小session失效的概率。通過zookeeper client 與server設置更長的session超時時間。(參考下一問題)

三、 為什么zookeeper_init設置recv_timeout較長卻沒有效果

問題描述:

zookeeper_init設置recv_timeout 100000ms,但客戶端與服務端斷開連接30s就session失效了。

問題分析:

關於session超時時間的確定:zookeeper_init中設置的超時時間並非真正的session超時時間,session超時時間需要 server與client協商,業務通過zoo_recv_timeout(zhandle_t* zh)獲取server與client協商后的超時時間。服務端: minSessionTimeout (默認值為:tickTime * 2) ,  maxSessionTimeout(默認值為:tickTime * 20), ticktime的默認值為2000ms。所以session范圍為4s ~ 40s 。客戶端:  sessionTimeout, 無默認值,創建實例時設置recv_timeout 值。經常會認為創建zookeeper客戶端時設置了sessionTimeout為100s,而沒有改變server端的配置,默認值是 不會生效的。 原因: 客戶端的zookeeper實例在創建連接時,將sessionTimeout參數發送給了服務端,服務端會根據對應的  minSession/maxSession Timeout的設置,強制修改sessionTimeout參數,也就是修改為4s~40s 返回的參數。所以服務端不一定會以客戶端的sessionTImeout做為session expire管理的時間。

問題解決:

增加zookeeper_init recv_timeout大小的同時,需要配置tickTime的值。
tickTime設置是在 conf/zoo.cfg 文件中

# The number of milliseconds of each
ticktickTime=2000  (默認)
注: tickTime 心跳基本時間單位毫秒,ZK基本上所有的時間都是這個時間的整數倍。

四、 zoo_get_children內存泄露問題

問題描述:

調用zoo_get_children函數出現內存泄露問題。

問題分析:

通過查看代碼發現問題在於 ZOOAPI int zoo_get_children(zhandle_t *zh, const char *path, int watch,struct String_vector *strings), 該API中String_vector *strings結構體定義如下:

 

 

Zookeeper API將getchildren結果通過String_vector結構體返回時,malloc分配內存,將子節點所有目錄存放在data中,而釋放內存需要有客戶端來做處理。

問題解決:

調用zoo_get_children(zh, path, watch, strings);需要通過調用zookeper提供的釋放內存的方法:deallocate_String_vector(strings)。

 

 

五、 如何正確設置和獲取watcher

Watcher 設置是開發中最常見的,需要搞清楚watcher的一些基本特征,對於exists、getdata、getchild對於節點的不同操作會收到不同的 watcher信息。對父節點的變更以及孫節點的變更都不會觸發watcher,而對watcher本身節點以及子節點的變更會觸發watcher,具體參照下表。

操作 方法 觸發watcher watcher state watcher type watcher path
Create當前節點 getdata × × × ×
getchildren 3 4
exists × × × ×
set當前節點 getdata 3 3
getchildren × × × ×
exists 3 3
delete當前節點 getdata 3 2
getchildren 3 2
exists 3 2
create子節點 getdata × × × ×
getchildren 3 4
exists × × × ×
set子節點 getdata × × × ×
getchildren × × × ×
exists × × × ×
delete子節點 getdata × × × ×
getchildren 3 4
exists × × × ×
恢復連接 getdata 1 -1 ×
getchildren 1 -1 ×
exists 1 -1 ×
恢復連接session未超時 getdata -112 -1 ×
getchildren -112 -1 ×
exists -112 -1 ×
恢復連接session超時 getdata 3 -1 ×
getchildren 3 -1 ×
exists 3 -1 ×
注: state = 2 表示刪除事件;state = 3表示節點數據變更;state =4表示子節點事件;state = -1表示session事件。 type = -112表示session失效;type = 1表示session建立中;tpye = = 3表示session建立成功。×表示否,√表示是。

六、 zookeeper連接數問題

問題描述:

zookeeper服務器都運行正常,而客戶端連接異常。

問題分析:

這是由於zookeeper client連接數已經超過了zookeeper server獲取的配置最大連接數。所以導致zookeeper client連接失敗。

解決方法:

修改zookeeper安裝目錄下 conf/zoo.cfg文件。將maxClientCnxns參數改成更大的值。

七、 zookeeper服務器安裝相關問題

問題一:是否可以只裝一個zookeeper服務器。

問題解答:

可以安裝,此時沒有leader,follow,此時zookeeper server狀態為standalone。

./zkServer.sh status
JMX enabled by default
Using config: /home/bbs/zookeeper-3.4.5/bin/../conf/zoo.cfg
Mode: standalone

關於zoo.cfg配置:

tickTime=2000initLimit=10
syncLimit=5
dataDir=../data
clientPort=4181

 問題二:開發沒有足夠機器,一台機子上是否裝三個zookeeper服務器集群。

問題解答:

這種安裝模式只能說是一種偽集群模式。三個zookeeper服務器都安裝在同一個服務器(platform)上,需保證clientPort不相同。
將zookeeper安裝包分別解壓在三個目錄server1,server2,server3下,配置文件zoo.cfg
Server1配置文件 zoo.cfg,server1在data目錄下增加文件myid內容為1。

dataDir=../datadata
LogDir=../dataLog
clientPort=5181
server.1=platform:5888:6888
server.2= platform:5889:6889
server.3= platform:5890:6890

Server2配置文件 zoo.cfg,server1在data目錄下增加文件myid內容為2。

dataDir=../datadata
LogDir=../dataLog
clientPort=6181
server.1=platform:5888:6888
server.2= platform:5889:6889
server.3= platform:5890:6890

Server3配置文件 zoo.cfg,server1在data目錄下增加文件myid內容為3。

 

dataDir=../datadata
LogDir=../dataLog
clientPort=7181
server.1=platform:5888:6888
server.2= platform:5889:6889
server.3= platform:5890:6890

以上出處“UC技術博客” http://tech.uc.cn/?p=1189

 

啟動zookeeper中的常見問題

1.     啟動zookeeper后出現noClassFound等等錯誤,例如:

Exception in thread "main" java.lang.NoSuchMethodError: method java.lang.management.ManagementFactory.getPlatformMBeanServer with signature ()Ljavax.management.MBeanServer; was not found.

  at org.apache.zookeeper.jmx.ManagedUtil.registerLog4jMBeans(ManagedUtil.java:48)

  at org.apache.zookeeper.server.quorum.QuorumPeerMain.runFromConfig(QuorumPeerMain.java:114)

  at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:103)

  at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:7

可能原因是該服務器的jdk版本不正確,或是環境變量未設置好。

例如,原來的linux下已經裝有jdk-1.4,然后又安裝了新版本的jdk-1.6,我們按照網上教程的步驟安裝好zookeeper並設置環境變量后,

echo $JAVA_HOME顯示java-1.6,

但是用java -version命令發現,仍然顯示java-1.4,說明環境變量未配好。zookeeper讀取的jdk版本仍然是舊版本的jdk-1.4。

解決方法是在/etc/bashrc文件的末尾,

export JAVA_HOME=/usr/java/jdk1.6.0_23

export JRE_HOME=$JAVA_HOME/jre

export PATH=$JAVA_HOME/bin:$PATH

//這里要注意,應該將$PATH放在尾部而不是放在頭部,網上有安裝教程寫的是$PATH :$JAVA_HOME/bin,這樣zookeeper讀取的將是$PATH中的jdk舊版本而出錯。

export CLASSPATH=.:$JAVA_HOME/lib/*.jar

2. 當一台或某台機器反復出現cannot open channel to xxxx:2888/3888,報錯(例如無法與leader進行同步等等錯誤),無法完成選舉(這個錯誤以前一直有出現,但是時有時無,不知道為什么)。

可能原因是防火牆開啟,導致某台機器的端口不能開啟,一般是2888不能開啟。linux下的很多分布式應用會要求關閉防火牆。。。所以還是干脆關閉算了。今天把防火牆直接關閉后zookeeper啟動正常。

用命令service iptables status查看,顯示一系列消息,表示防火牆處於開啟狀態;可以用service iptables stop關閉防火牆。但是這個只是臨時關閉防火牆。

要使系統啟動時不自動啟動防火牆,則可以使用命令chkconfig –list iptables查看防火牆信息,chkconfig iptables off關閉防火牆。以后若要打開,用chkconfig iptables on命令。

3.Zookeeper能夠正常啟動,但是顯示如下錯誤:

Starting zookeeper…

./zkServer.sh: line 80: /home /sysdata/zookeeper/zookeeper-data/zookeeper_server.pid: No such file or directory

STARTED

在配置文件zoo.cfg文件中指定了zookeeper啟動的pid文件的生成位置:dataDir=/home /sysdata/zookeeper/zookeeper-data,但是我們發現該pid並沒有生成。而且想要停止zookeeper顯然也不能成功:

Stopping zookeeper ...

error: could not find file /zookeeper_server.pid。

zoo.cfg文件中的給dataDir路徑賦值前多了一個空格!zookeeper在讀取此配置文件時會把空格也讀進文件名,將此空格刪去后zookeeper啟動、關閉就正常了!

摘自 http://hi.baidu.com/luhao8415/item/23c6e7f075aa18b730c1993a

Zookeeper常見錯誤筆記

標簽:class   style   代碼   com   log   使用   java   文件   http   

原文:http://www.cnblogs.com/binyue/p/4270150.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM