一、zookeeper 的安裝與配置:
1.zookeeper安裝
下載:https://zookeeper.apache.org/ 建議下載zookeeper 3.4.6穩定版的, 3.5版本的在搭建集群時,會出現服務啟動失敗的錯誤。
安裝: 解壓 即可
安裝C 語言 api:
進入./zookeeper/src/c目錄
./configure
make
make install
2.集群配置
Zookeeper 的配置文件在 conf 目錄下,這個目錄下有 zoo_sample.cfg 和 log4j.properties,需要將 zoo_sample.cfg 改名為 zoo.cfg,因為 Zookeeper 在啟動時會找這個文件作為默認配置文件。下面詳細介紹一下,這個配置文件中各個配置項的意義。
tickTime=2000
dataDir= /home/zoo/data
clientPort=2181
- tickTime:這個時間是作為 Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。
- dataDir:顧名思義就是 Zookeeper 保存數據的目錄,默認情況下,Zookeeper 將寫數據的日志文件也保存在這個目錄里。
- clientPort:這個端口就是客戶端連接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。
當這些配置項配置好后,你現在就可以啟動 Zookeeper 了,啟動后要檢查 Zookeeper 是否已經在服務,可以通過 netstat – ano 命令查看是否有你配置的 clientPort 端口號在監聽服務。
集群模式
Zookeeper 不僅可以單機提供服務,同時也支持多機組成集群來提供服務。實際上 Zookeeper 還支持另外一種偽集群的方式,也就是可以在一台物理機上運行多個 Zookeeper 實例,下面將介紹集群模式的安裝和配置。
Zookeeper 的集群模式的安裝和配置也不是很復雜,所要做的就是增加幾個配置項。集群模式除了上面的三個配置項還要增加下面幾個配置項:
initLimit=5
syncLimit=2
server.1=192.168.211.1:2888:3888
server.2=192.168.211.2:2888:3888
- initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這里所說的客戶端不是用戶連接 Zookeeper 服務器的客戶端,而是 Zookeeper 服務器集群中連接到 Leader 的 Follower 服務器)初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是 tickTime)長度后 Zookeeper 服務器還沒有收到客戶端的返回信息,那么表明這個客戶端連接失敗。總的時間長度就是 5*2000=10 秒
- syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2*2000=4 秒
- server.myid=ip:port1:port2:其中 myid 是一個數字,表示這個是第幾號服務器;ip是這個服務器的 ip 地址;port1表示的是這個服務器與集群中的 Leader 服務器交換信息的端口;port2表示的是萬一集群中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。如果是偽集群的配置方式,由於 ip 都是一樣,所以不同的 Zookeeper 實例通信端口號不能一樣,所以要給它們分配不同的端口號。
除了修改 zoo.cfg 配置文件,集群模式下還要配置一個文件 myid,這個文件在 dataDir 目錄下,這個文件里面就有一個數據就是 A 的值,Zookeeper 啟動時會讀取這個文件,拿到里面的數據與 zoo.cfg 里面的配置信息比較從而判斷到底是那個 server。
二、Zookeeper的使用:
1.服務端的啟動:
進入/bin目錄,使用./zkServer.sh start 啟動zookeeper服務。 使用./zkServer.sh stop 停止服務。./zkServer.sh status 查看服務狀態 (leader or follower).
2.客戶端命令的使用:
進入/bin目錄下,使用 ./zkCli.sh –server host:port 登陸服務,例如
./zkCli.sh -server 192.168.1.91:2181,鍵入任意字符出現以下help命令。
[zk: localhost:2181(CONNECTED) 1] help
ZooKeeper -server host:port cmd args
connect host:port
get path [watch]
ls path [watch]
set path data [version]
delquota [-n|-b] path
quit
printwatches on|off
create [-s] [-e] path data acl
stat path [watch]
close
ls2 path [watch]
history
listquota path
setAcl path acl
getAcl path
sync path
redo cmdno
addauth scheme auth
delete path [version]
setquota -n|-b val path
- create [-s] [-e] path data acl
其中”-s”表示創建一個順序自動編號的節點,”-e”表示創建一個臨時節點.默認為持久性節點
例如:創建一個持久性節點和臨時節點
[zk: localhost:2181(CONNECTED) 7] create /test null
Created /test
[zk: localhost:2181(CONNECTED) 8] create -e /test0 null
Created /test0
當會話退出,臨時節點將會自動刪除,並且臨時節點無子節點。
關於ACL的設置和使用在下一節單獨介紹。
2.get path [watch]和set path data [version]
get是獲取Znode的數據及相關屬性,而set是修改此Znode的數據.
3.ls path [watch]
查看Znode的子節點
4.stat path [watch]
查看Znode的屬性
5.delete path [version]
刪除Znode,前提若有子節點,先刪除其子節點
6.addauth scheme auth
認證授權,若某個節點需要認證后才能查看,就需要此命令,具體見下節。
3.ACL 的使用
傳統的文件系統中,ACL分為兩個維度,一個是屬組,一個是權限,子目錄/文件默認繼承父目錄的ACL。而在Zookeeper中,node的ACL是沒有繼承關系的,是獨立控制的.
多集群共用zookeeper又涉及一個權限隔離的問題。zookeeper本身提供了ACL機制,表示為scheme:id:permissions,第一個字段表示采用哪一種機制,第二個id表示用戶,permissions表示相關權限,如只讀,讀寫,管理等。
scheme: scheme對應於采用哪種方案來進行權限管理,zookeeper實現了一個pluggable的ACL方案,可以通過擴展scheme,來擴展ACL的機制。zookeeper-3.4.4缺省支持下面幾種scheme:
world: 它下面只有一個id, 叫anyone, world:anyone代表任何人,zookeeper中對所有人有權限的結點就是屬於world:anyone的
auth: 它不需要id, 只要是通過authentication的user都有權限(zookeeper支持通過kerberos (http://www.cnblogs.com/jankie/archive/2011/08/22/2149285.html)來進行authencation, 也支持username/password形式的authentication)
digest: 它對應的id為username:BASE64(SHA1(password)),它需要先通過username:password形式的authentication
ip: 它對應的id為客戶機的IP地址,設置的時候可以設置一個ip段,比如ip:192.168.1.0/16, 表示匹配前16個bit的IP段
super: 在這種scheme情況下,對應的id擁有超級權限,可以做任何事情(cdrwa)
另外,zookeeper-3.4.4的代碼中還提供了對sasl的支持,不過缺省是沒有開啟的,需要配置才能啟用,具體怎么配置在下文中介紹。
* sasl: sasl的對應的id,是一個通過sasl authentication用戶的id,zookeeper-3.4.4中的sasl authentication是通過kerberos來實現的,也就是說用戶只有通過了kerberos認證,才能訪問它有權限的node.(關於sasl 參考:http://www.wxdl.cn/cloud/zookeeper-sasl.html)
id: id與scheme是緊密相關的,具體的情況在上面介紹scheme的過程都已介紹.
permission: zookeeper目前支持下面一些權限:
權限 |
描述 |
備注 |
CREATE |
有創建子節點的權限 |
|
READ |
有讀取節點數據和子節點列表的權限 |
|
WRITE |
有修改節點數據的權限 |
無創建和刪除子節點的權限 |
DELETE |
有刪除子節點的權限 |
|
ADMIN |
有設置節點權限的權限 |
客戶端示例:
- create [-s] [-e] path data acl
create /acl test world:anyone:rwd
Created /test
- create -s /test/test null digest:test:V28q/NynI4JI3Rk54h0r8O5kMug=:rwcda
Created /test/test0000000000
- getAcl /acl 查看路徑的acl信息
- setAcl /test digest:test:V28q/NynI4JI3Rk54h0r8O5kMug=:r
- setAcl /test auth:username:password:crdwa
- addauth /<node-name> digest <username>:<password>
ACL的原理:
ZooKeeper 的權限管理通過Server、Client 兩端協調完成:
(1) Server端
一個ZooKeeper 的節點存儲兩部分內容:數據和狀態,狀態中包含ACL 信息。創建一個znode 會產生一個ACL 列表,列表中每個ACL 包括:
① 權限perms
② 驗證模式scheme
③ 具體內容expression:Ids
例如,當scheme="digest" 時, Ids 為用戶名密碼, 即"root :J0sTy9BCUKubtK1y8pkbL7qoxSw"。ZooKeeper 提供了如下幾種驗證模式:
① Digest: Client 端由用戶名和密碼驗證,譬如user:pwd
② Host: Client 端由主機名驗證,譬如localhost
③ Ip:Client 端由IP 地址驗證,譬如172.2.0.0/24
④ World :固定用戶為anyone,為所有Client 端開放權限
(2) 客戶端
Client 通過調用addAuthInfo()(java, c為zoo_add_auth)函數設置當前會話的Author信息。Server 收到Client 發送的操作請求(除exists、getAcl 之外),需要進行ACL 驗證:對該請求攜帶的Author 明文信息加密,並與目標節點的ACL 信息進行比較,如果匹配則具有相應的權限,否則請求被Server 拒絕。
三、zookeeper原理機制
1.文件系統
Zookeeper維護一個類似文件系統的數據結構:
每個子目錄項如 NameService 都被稱作為 znode,和文件系統一樣,我們能夠自由的增加、刪除znode,在一個znode下增加、刪除子znode,唯一的不同在於znode是可以存儲數據的。
有四種類型的znode:
1、PERSISTENT-持久化目錄節點
客戶端與zookeeper斷開連接后,該節點依舊存在
2、 PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
客戶端與zookeeper斷開連接后,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號
3、EPHEMERAL-臨時目錄節點
客戶端與zookeeper斷開連接后,該節點被刪除
4、EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
客戶端與zookeeper斷開連接后,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號
2.通知機制
客戶端注冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端。
Zookeeper 的watch函數時一次性觸發的,即一 個watch事件將會在數據發生變更時發送給客戶端。例如,如果客戶端執行操作getData(“/znode1″, true),而后 /znode1 發生變更或是刪除了,客戶端都會得到一個 /znode1 的watch事件。如果 /znode1 再次發生變更,則在客戶端沒有設置新的watch的情況下,是不會再給這個客戶端發送watch事件的。
這就是說,一個事件會發送向客戶端,但可能在在操作成功的返回值到達發起變動的客戶端之前,這個事件還沒有送達watch的客戶端。Watch是異步發送 的。但ZooKeeper保證了一個順序:一個客戶端在收到watch事件之前,一定不會看到它設置過watch的值的變動。網絡時延和其他因素可能會導 致不同的客戶端看到watch和更新返回值的時間不同。但關鍵點是,每個客戶端所看到的每件事都是有順序的。
四、使用場景
1.配置同步:
- 搭建zookeeper集群,在集群服務器上創建永久節點如:Authorization
- 需要更新緩存的客戶機器,連接至集群,並通過zookeeper watch機制對Authorization節點設置watch。
- 當數據庫認證信息發生變化時,對 Authorization 節點數據進行更新,從而觸發客戶機的watch 函數,在watch函數中進行更新緩存的操作。
注意事項:
- watch 時一次性觸發的,因此在watch函數觸發后,需要重新注冊,從而實現永久監聽。
- 由於網絡原因,或者更新操作過於頻繁時,在客戶機處理更新操作,沒有注冊新的watch間隙,數據庫的認證信息發生變化時,這時會出現客戶端緩存和數據庫數據不一致的錯誤,因此,在watch函數結束后,通過再次獲取Authorization的相關信息(程序中使用的是mzxid)與之前的進行比較,若不一致,需要再次進行更新緩存操作。
- zookeeper session 失效問題 http://blog.csdn.net/kobejayandy/article/details/26289273當客戶端收到SESSIONEXPIRED狀態信息后,由於之前設置的watch將失效,因此,進行了關閉之前的連接,重新開始連接,並設置watch函數的操作。
2.集群管理
使用zookeeper可以進行集群管理,主要針對兩點
- 是否有機器的加入或退出
解決這個問題,可以在約定一個父目錄,gropmember,然后再父目錄下面,每個機器創建臨時節點,並且監聽父目錄的子節點變化消息,一旦有機器退出集群,對應的子節點也將被刪除,其它機器將受到通知。同樣,當加入新的機器時,其它機器也將受到通知。
- Master的選舉
Master的選舉與上面的原理大致一致,所有機器創建臨時子節點並按順序編號,每次選擇編號最小的子節點對應的機器作為master即可。
另外:
zookeeper
zoo_get(zhandle_t *zh, const char *path, int watch, char *buffer,
int* buffer_len, struct Stat *stat);
1.在傳遞參數時,buffer_len 的值是buffer緩沖的大小,當zoo_get成功返回后,buffer_len將被至為對應node節點數據的長度
2.如何確定buffer的大小? 可以設置一個大約值,然后當zoo_get 返回后,從stat結構體中獲取node數據長度,與返回的buffer_len 進行比較,若是不相符,說明緩沖區小了,這時可以拿到正確的長度,再次get即可。
stat結構體:
struct Stat {
int64_t czxid;
int64_t mzxid;
int64_t ctime;
int64_t mtime;
int32_t version;
int32_t cversion;
int32_t aversion;
int64_t ephemeralOwner;
int32_t dataLength;
int32_t numChildren;
int64_t pzxid;
};