其實都不用想單機邏輯肯定非常簡單,畢竟一台伺服器,很多都很好實現。
整個流程圖如下:
其中箭頭中的數字是呼叫的順序,橫向表示在同乙個方法中,而黃色區域為該方法的注釋。單機啟動的整個體系就是這個展開的。
從啟動項就能明白,我們指定了配置檔案啟動,所以肯定是把配置檔案的引數解析出來,然後載入到記憶體中,最後初始化好server即可。因為解析配置都很簡單,所以就不說了,主要是後面放到對應的配置類之後做了什麼事?怎麼初始化的?當乙個client傳送請求應該怎麼處理的?這個才是重點需要了解的。
我們直接定位到org.apache.zookeeper.server.zookeeperservermain#runfromconfig這個方法。你可以在這裡打個斷點,直接就粗暴的認為前面就是讀取檔案,實際還有判斷判斷集群單機,快照和事務的定時策略等。
public
void
runfromconfig
(serverconfig config)
throws ioexception
}catch
(interruptedexception e)
finally
}}
這個方法的注釋我也寫出來了。其實重點還是cnxnfactory.startup(zkserver);這行**。前面的**就認為是為整個啟動做準備。
跟蹤到這個**下面:
@override
public
void
startup
(zookeeperserver zks)
throws ioexception,
interruptedexception
這個就很重要了。可以說是單機最核心的啟動流程,針對這四步乙個乙個的說。
1、start()方法:它啟動了乙個執行緒,呼叫執行緒的start()方法,所以直接定位到run()方法中。
public
void
run(
) arraylist
selectedlist =
newarraylist
( selected)
; collections.
shuffle
(selectedlist)
;for
(selectionkey k : selectedlist)
else
}elseif(
(k.readyops()
&(selectionkey.op_read | selectionkey.op_write))!=
0)else}}
selected.
clear()
;}catch
(runtimeexception e)
catch
(exception e)
}closeall()
; log.
info
("nioservercnxn factory exited run method");
}
也就不詳細說了,其實就是不斷的獲取客戶端的資料。
2、setzookeeperserver(zks)比較簡單,就是把配置設定到單機的的啟動類中。
3、zks.startdata():這個方法就比較重要了,因為比如zookeeper啟動過一段時間,然後停止了,但是要再次啟動這些資料再**呢?zookeeper也是做了持久化了的,再次啟動之前就需要把這些配置讀取資料到記憶體。
public
void
startdata()
throws ioexception, interruptedexception if(
!zkdb.
isinitialized()
)}
public
void
loaddata()
throws ioexception, interruptedexception
else
// clean up dead sessions
linkedlist
deadsessions =
newlinkedlist
();for
(long session : zkdb.
getsessions()
)}zkdb.
setdatatreeinit
(true);
for(
long session : deadsessions)
}
我們看看setzxid(zkdb.loaddatabase());這個方法,從頭初始化。
public
long
loaddatabase()
throws ioexception
因為很多其實都在注釋中了,就不多說了。
4、zks.startup()我們在前面做了什麼事呢?再來回想一下。
1、啟動執行緒:為了能夠接收客戶端的資料。
2、配置出乙個zookeeperserver。
3、把zookeeper恢復到上次關閉的狀態。
所以第四步應該做什麼呢?仔細想想前3步。可有什麼沒有做的?
是的。我們還沒有去處理並返回客戶端的請求。所以我們最後啟動是做什麼呢?肯定是初始化請求處理啦!來來來,我們看看這個方法做了什麼。
public
synchronized
void
startup()
//開啟乙個session跟蹤
startsessiontracker()
;//設定乙個請求處理器。傳說中的責任鏈模式。這個有點繞。不過理解了這個模式就好懂。
//流程就是preprequestprocessor->syncrequestprocessor->finalrequestprocessor
setuprequestprocessors()
;//幹嘛的不知道
registerjmx()
;//設定狀態為執行
setstate
(state.running)
;//啟動完成。開始喚醒所有執行緒。這裡不知道有什麼作用,我就算是注釋掉操作照樣能執行。
//但是上一步setstate(state.running);注釋掉客戶端就能連證明至少要到setstate後server才初始化完成。
notifyall()
;}
其它不說,我認為最重要的**是:
setuprequestprocessors()
;
我們看看這個方法裡面是什麼。
protected
void
setuprequestprocessors()
因為這個相當於使用了3個執行緒去處理,每一步都有自己的負責的事情,故而稱之為責任鏈模式(也可以認為是流水線)。至於每個執行緒中的run()方法就不帶進去看了。這個相信用了一段時間zookeeper的人裡面的run()方法應該能看懂。後面這裡補個請求處理鏈的流程圖。
zookeeper學習之路二
zookeeper 是以fast paxos演算法為基礎的,並做了一些優化,解決了活鎖 有多個交錯提交情況時,會出現相互排斥無法成功提交 的問題。zookeeper 基本運轉流程,1.選舉 leader 2.同步資料 3.選舉 leader 標準的一致性 4.leader 要有最高的 zxid 事務...
ZooKeeper學習筆記(二)
2.將解壓後的zookeeper複製出2份,將這三分分別命名 如 z1,z2,z3 ticktime 2000 initlimit 10 synclimit 5 datadir data clientport 2181 server.1 127.0.0.1 2222 2223 server.2 12...
Zookeeper系列二 Zookeeper原理
從擴充套件性開始講起,在zk中存在的角色有leader,follower,observer。zk是讀寫分離的,所有的寫都會壓到leader上面,讀操作可以在follower上面完成。只有follower才能選擇,observer比follower級別還低。observer只是為了放大查詢能力。乙個集...