客户端是开发人员使用Zookeeper的主要的途径,以下内容将对Zookeeper的内部原理进行详细的学习和讲解。ZooKeeper的客户端主要有一下几个核心组件组成:

  • Zookeeper:提供客户端访问ZooKeeper服务器的API.
  • ClientWatchManager:负责管理客户端注册的Watcher.
  • HostProvider:客户端地址列表管理器。
  • ClientCnxn:客户端核心线程,其内部包含连个线程及SendThread和EvnentThread。SendThread是一个IO线程主要负责客户端和服务端之间的网络通信;后者是一个事件处理线程,主要负责对服务端时间进行处理。

  客户端的整体架构如下:

 Zookeeper客户端介绍

实例

  下面使用具体的实例结合源码来分析Zookeeper源码创建的过程:如下代码是一个单例的ZooKeeperSupport可以用来回去Zookeeper客户端对象:

 1 public class ZookeeperSupport {    
 2     private static volatile ZooKeeper zooKeeper = null; // zookeeper连接,在初始化zk配置时设置
 3     public static final Integer zooKeeperLock = new Integer(1);
 4     public static boolean isUseZk = true; // 是否使用zk,默认使用,当zk连接发生异常时不再使用
 5     public static final long ZK_CONNECT_TIMEOUT = 1L; //zk连接的超时时间设置,单位为秒
 6     
 7     public static ZooKeeper getZooKeeper() {
 8         // 如果zookeeper为null 或者连接不可用,则重新获取连接,一般情况下,不会触发
 9         if (zooKeeper == null || !zooKeeper.getState().isAlive()) {
10             synchronized (zooKeeperLock) {
11                 // 如果发现zk不再使用,则不再创建新的zk,直接返回
12                 if (isUseZk) {
13                     if (zooKeeper == null || !zooKeeper.getState().isAlive()) {
14                         try {
15                             zooKeeper = createNewZookeper();
16                         } catch (Exception e) {
17                             Constant.log_cron.error("[initZkConfig] error happen where new zookeeper", e);
18                         }
19                     }
20                 }
21             }
22         }
23         return zooKeeper;
24     }
25     
26     public static void setZooKeeper(ZooKeeper zooKeeper) {
27         ZookeeperSupport.zooKeeper = zooKeeper;
28     }
29     
30     /**
31      * zookeeper启动时,异步启动两个线程,所以new之后并不代表连接已经建立,此时如果调用zk的一些方法会抛ConnectionLoss的异常
32      * 为了避免这种情况,封装new方法,每次new的时候去等待连接已经建立才做后面的步骤
33      * 
34      * @return
35      * @throws Exception
36      */
37     public static ZooKeeper createNewZookeper() throws Exception {
38         CountDownLatch connectedLatch = new CountDownLatch(1);
39         ZooKeeper zooKeeper = new ZooKeeper(ZKConfig.getInstance().getConnectUrl(), ZKConfig.getInstance().getTimeout(), new DefaultWatcher(connectedLatch));    
40         if (States.CONNECTING == zooKeeper.getState()) {
41             boolean ret = connectedLatch.await(ZK_CONNECT_TIMEOUT, TimeUnit.SECONDS);
42             // 如果等待超时了,还没有收到连接成功的通知,则说明zk不可用,直接不用zk,并报警
43             if(!ret){
44                 isUseZk = false;
45             }
46         }
47         return zooKeeper;
48     }    
49 }
View Code

相关文章: