系統結構:
2 節點角色:
- Server1、Server2、Server3構成了ZooKeeper註冊中心,通過LeaderElection,Server2爲Leader,Server1和Server3爲Follower;
- Server1和Server2本身還提供服務,假設Server3不提供任何服務;
- Server4對外提供服務,但沒有部署ZooKeeper服務器,不加入ZooKeeper註冊中心;
- Client遠程調用Server1、Server2、Server4的服務。
3 調用關係:
- Server1、Server2、Server4中對外發布的服務,在啓動時向ZooKeeper註冊中心註冊服務;
- 服務消費者(Client)向註冊中心獲取服務提供者地址列表,直接調用提供者;
- 註冊中心全部宕機,不影響已運行的提供者和消費者,消費者在本地緩存了提供者列表;
- 服務消費者和服務提供者可連接註冊中心任意一臺ZooKeeper服務器。
4 ZooKeeper集羣部署
三個ZooKeeperServer
5 ZooKeeper註冊中心目錄結構
6 服務提供者向註冊中心註冊服務信息
服務提供者將服務需要的信息通過create()函數,在註冊中心創建對應的節點
/**
* registerService()
* register methord add on zookeeper
* @param args
* @throws IOException
* @throws InterruptedException
* @throws KeeperException
*/
privatestaticvoidregisterService() throws IOException, KeeperException, InterruptedException {
if (null == zk.exists("/serviceAlive", false))
zk.create("/serviceAlive", "serviceAlive".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
if (null != zk.exists("/serviceAlive", false))
zk.create("/serviceAlive/serviceAdd", "add".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
if (null == zk.exists("/ZooServerA", false))
zk.create("/ZooServerA", "ZooServerA".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
if (null == zk.exists("/ZooServerA/add", false))
zk.create("/ZooServerA/add", "add".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
if (null == zk.exists("/ZooServerA/add/url", false))
zk.create("/ZooServerA/add/url", "http://localhost:6666/add".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
if (null == zk.exists("/ZooServerA/add/namespace", false))
zk.create("/ZooServerA/add/namespace", "http://server.testzookeeper.dhong.com/".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
if (null == zk.exists("/ZooServerA/add/name", false))
zk.create("/ZooServerA/add/name", "ZooKeeperServerAService".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
String address = "http://localhost:6666/add";
Endpoint.publish(address, new ZooKeeperServerA());
System.out.println("service add started.");
}
7 服務消費者從註冊中心獲取服務信息
服務消費者通過getData()從註冊中心獲取使用服務所需的信息。
//從註冊中心獲得serviceAdd需要的信息
String urlAdd = new String(zkA.getData("/ZooServerA/add/url", false, null));
String nameSpaceAdd = new String(zkA.getData("/ZooServerA/add/namespace", false, null));
String nameAdd = new String(zkA.getData("/ZooServerA/add/name", false, null));
8 註冊中心實時監視提供者服務狀態
服務啓動時,服務提供者在註冊中心創建一個臨時的目錄"/serviceAlive/serviceAdd",當服務提供者與註冊中心連接中斷後,該臨時節點會自動刪除,註冊中心通過觸發與該節點關聯的Watcher,從而將服務狀態通知到服務的消費者。
if (null == zk.exists("/serviceAlive", false))
zk.create("/serviceAlive", "serviceAlive".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
if (null != zk.exists("/serviceAlive", false))
zk.create("/serviceAlive/serviceAdd", "add".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
9 註冊中心實時通知消費者服務狀態
- 服務消費者在使用服務前,檢查"/serviceAlive/serviceAdd"節點是否存在,從而判斷服務是否可用,並將該節點目錄綁定到watchSeiverceAdd;
//檢查“/serviceAlive/serviceAdd”節點是否存在,判斷服務是否可用
if (null != zkA.exists("/serviceAlive/serviceAdd", watchSeiverceAdd)) {
serviceAdd = true;
}
- 當節點"/serviceAlive/serviceAdd"狀態發生變化時,註冊中心會自動通知到watchSeiverceAdd;收到通知的Watcher在process()方法中做相應的處理
//watchSeiverceA用於監視serviceAdd是否可用
privatestatic Watcher watchSeiverceAdd = new Watcher() {
//服務A啓停watch
@Override
publicvoid process(WatchedEvent event) {
if (serviceAdd == true)
serviceAdd = false;
else
serviceAdd = true;
System.out.println("<--------------------------------------serviceAdd status changed--------------------------------------->");
try {
zkA.exists("/serviceAlive/serviceAdd", watchSeiverceAdd);
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} ///Wather功能的一次性,處理完後重新註冊
}
};