zookeeper的API圍繞zookeeper的句柄而構建,每一個句柄表明與zookeeper的一個會話。
已經創建的一個會話若是端口,這會話會轉移到另外一臺zookeeper服務器上 只要會話還存活,這個句柄就有效,zookeeper客戶端會保持這個活躍的鏈接,以保證與zookeeper服務器之間的會話存活。
若是句柄關閉,zookeeper客戶端就會告知zookeeper服務器終止會話
若是zookeeper服務器發現客戶端已經死掉,就會是這個會話無效
若是客戶端以後嘗試從新鏈接zookeeper服務器,使用以前無效會話對應的句柄進行鏈接,那麼zookeeper服務器會通知客戶端,這個會話已經失效,使用這個句柄進行的任何操做都會返回錯誤。
建立zookeeper句柄的構造函數:
Zookeeper(String connectString,int sessionTimeout,Watch watcher)
connectString中包含了主機名和zookeeper服務器的端口
sessionTimeout以毫秒爲單位,表示zookeeper等待客戶端通信的最長時間。
watcher用於接收會話事件的一個對象,這個對象是咱們本身建立的。須要實現Watcher接口。
實現一個簡單的Watcher
public interface Watcher{
void process(WatchedEvent event);
}
public class Master implements Watcher {
Zookeeper zk;
Master(Zookeeper zk){
this.zk=zk;
}
void startZk() {
zk = Zookeeper(hostport,15000,this);
}
public void process(WatchedEvent event) {
System.out.println(event);
}
public static void main(String[] args) {
Master m = new Master();
m.startZk();
Thread.sleep(60000);
}
}
如今咱們啓動zookeeper服務器,而後運行Master,以後中止zookeeper服務器,並保持Master運行,你能夠看到synchronized事件以後發生了Disconnected事件,當開發者遇到Disconnected事件時,不要從新建立一個新鏈接,zookeeper客戶端庫負責爲你從新鏈接服務,當不幸遇到網絡問題或者服務器故障時,zookeeper能夠處理這些故障問題。
請不要嘗試去管理zookeeper客戶端鏈接。zookeeper客戶端庫會監控與zookeeper服務之間的鏈接,客戶度庫不只告訴咱們鏈接發生了問題,還會主動嘗試從新創建通信。
爲了確保同一時間只有一個主節點進程處於活動狀態,可使用zookeeper實現簡單的羣首選舉算法。全部潛在主節點進程都嘗試建立/master節點,但只有一個能成功,這個成功的進程就是主節點。
常量ZooDefs.Ids.OPEN_ACL_UNSAFE爲全部人提供了全部權限。
zookeeper能夠經過插件式的認證方法提供了每一個節點的ACL策略功能。
能夠經過如下代碼嘗試得到主節點權限:
zk.create("/master",
serverId.getBytes(),
OPEN_ACL_UNSAFE,
CreateMode.Ephemeral);
使用create方法會拋出兩種異常:KeeperException和InterruptedException。咱們須要確保咱們處理了這兩種異常,特別是ConnectionLossException(KeeperException異常的子類)和KeeperException。對於其餘異常咱們能夠忽略繼續執行,可是對於這兩種異常,create方法能夠已經成功了,所喲若是咱們做爲主節點就須要捕獲並處理他們。
ConnectionLossException異常發生於客戶端與zookeeper服務器失去鏈接時,通常常見的緣由因爲網絡緣由致使,例如網絡分區或者zookeeper服務器故障。當這個異常發生時,客戶端並不知道是在zookeeper服務器處理前丟失請求消息,仍是在處理後客戶端爲收到響應消息。
InterruptedException異常源於客戶端線程調用了Thread.interrupt,一般這是應爲應用程序部分關閉,但還在被其餘相關應用的方法使用。從字面看這個異常,進程會中斷本地客戶端的請求處理的進程,並使該請求處於爲之狀態。
以上兩種請求都會致使正常請求處理過程的中斷。
處理ConnectionLossException異常時,在羣首選舉時,咱們須要找到/master節點,若是進程是本身,就開始成爲羣首角色,可使用getData(String path,bool watch,Stat stat)代碼得到當前/master節點的數據。
zookeeper中全部同步調用方法都有對應的異步調用方法。經過異步調用方法,咱們能夠在單線程中同時進行多個調用,同時也能夠簡化咱們的實現方式。
void create(
String path,
byte[] data,
List<ACL> acl,
CreateMode createMode,
AsynCallback.StringCallback cb,(提供回調方法的對象)
Object ctx(用戶指定上下文信息,回調方法調用時傳入的對象實例)
)
回調對象實現只有一個方法StringCallback接口:
void processResult(int rc,String path,Object ctx,String name)
rc:返回調用的結果,OK或者與KeeperException異常對應的編碼值
path:咱們傳給create的path值
ctx:咱們傳給create的上下文參數
name:建立的znode節點名稱
調用成功後。path與name的值同樣,可是若是採用Create.Sequential模式,這兩個參數值就不會相等。
注意:只有一個單獨的線程會全部回調函數,若是回調函數阻塞,全部後續回調調用都會阻塞,所以通常不要在回到函數中集中操做或者阻塞操做。
zookeeper會嚴格維護執行順序,並提供強有力的有序保證,然而,在多線程下仍是須要當心面對順序問題,多線程下,當回調函數中包含重試邏輯的代碼時,一些常見的場景均可能致使錯誤發生,當遇到ConnectingLossException異常而補發一個請求時,新創建的請求可能排序在其餘線程中的請求以後,而實際上其餘線程中的請求應該在原來請求以後。