先談談watcher和watcheEvent
剛學zookeeper的時候械哟,都會被坑一次映凳,以為watcher的監(jiān)聽是永久的录别。其實不然耕渴,watcher在大多數(shù)時候都只調(diào)用一次拘悦。
zookeeper使用HashMap<Path,Watcher>維護了所有路徑的watcher,
private static class ZKWatchManager implements ClientWatchManager {
private final Map<String, Set<Watcher>> dataWatches = new HashMap<String, Set<Watcher>>();
private final Map<String, Set<Watcher>> existWatches = new HashMap<String, Set<Watcher>>();
private final Map<String, Set<Watcher>> childWatches = new HashMap<String, Set<Watcher>>();
所有不論注冊多少次萨螺,都只會有一個watcher存在窄做。當watcheEvent產(chǎn)生的時候,會移除對應path的watcher慰技,并且回調(diào)椭盏。
然而,當type=None的時候吻商,就不會移除watcher掏颊,會向所有watcher發(fā)送事件。
何時會產(chǎn)生type=None的事件呢艾帐?狀態(tài)轉(zhuǎn)變的時候乌叶!
初始化的sessionState=Disconnected,
所以第一次ping成功柒爸,(zookeeper client會不斷的給server發(fā)送ping指令)
會產(chǎn)生一個watchEvent:State=SyncConnected准浴,type=None,
此時sessionState=SyncConnected捎稚,所以后續(xù)的ping就不會產(chǎn)生事件了乐横。
當zk監(jiān)聽watcher的時候,如果發(fā)生網(wǎng)絡斷鏈今野,且在sessionTimeout/2的時間內(nèi)都沒有恢復連接葡公。
那么所有注冊的watcher都會接收到
state=Disconnected,type=None,path=Null的watchEvent
此時sessionState=Disconnected..
- 如果在剩下sessionTimeout/2的時間內(nèi)恢復連接,即ping通了
那么就會收到watchEvent:state=SyncConnected,type=None条霜,path=Null - 如果超過sessionTimeout時間恢復連接催什,那么就會收到
watchEvent:state=Expired,type=None,path=Null
此時表示zookeeper客戶端真正與服務端失去連接,就需要重建zookeeper的客戶端了宰睡。 - 如果超過sessionTimeout時間也沒恢復連接蒲凶,只有等恢復連接才會收到Expired事件气筋。
所以對于watcheEvent的事件的處理方式是:
- DisConneted 無視,因為連不上你做啥事都沒用豹爹,也就改改某些狀態(tài)裆悄,能連上的話要么收到SyncConneted事件,要么收到Expired 事件
- Expired重新構(gòu)建zookeeper客戶端臂聋。
- SyncConnected
- 對于type!=None重新注冊watcher.
- 對于監(jiān)聽的type做后續(xù)處理
再談談zookeeper客戶端操作的Code
- 同步操作會收到KeeperException
- 異步操作會收到rc
對于KeeperException 可以使用code()得到Code光稼,對于rc,可以使用KeeperException.Code.get(rc)得到Code
Code表示你這次操作的結(jié)果
例如對于delete(path,version)
- 如果節(jié)點存在那么會收到ok
- 如果節(jié)點不存在那么會收到NoNode
那么如果是斷連呢孩等?
- 如果正處于斷連艾君,那么會產(chǎn)生ConnectionLoss。
- 如果sessionExpired或者zookeeper.close那么會收到sessionExpired
所以對于rc處理方式是:
- ConnectionLoss肄方,局部重試
- sessionExpired冰垄,重建zookeeper客戶端
- 其他,業(yè)務邏輯處理权她。
對于zookeeper的初略理解虹茶,有問題可以指點指點。
另外關(guān)于測試隅要。
模擬zookeeper的sessionExpired可以看看curator的KillSession