HTable是HBase提供的一个主要客户端接口, 通过它可以实现与HBase集群连接, 进而实现CRUD等一系列功能。

  1. HTable如何实现与HBase集群的连接?
HTable是如何知道HBase集群中的HMaser和HRegionServer, 答案是通过Zookeeper, zookeeper是一个分布式协调系统, HMaser,HRegionServer在启动后会自动在zookeeper中注册自己的地址。
      HTable实例构造后会查找zookeeper配置, 与zookeeper取的连接, 进而获取HMaser,HRegionServer信息
加载zookeeper配置流程如下:
通过org.apache.hadoop.hbase.zookeeper.ZKConfig 类来加载zookeeper配置:
 

  1. public static Properties makeZKProps(Configuration conf) {  
  2.   // First check if there is a zoo.cfg in the CLASSPATH. If so, simply read  
  3.   // it and grab its configuration properties.  
  4.   ClassLoader cl = HQuorumPeer.class.getClassLoader();  // zoo.cfg必须在CLASSPATH路径下
  5.   final InputStream inputStream =  
  6.     cl.getResourceAsStream(HConstants.ZOOKEEPER_CONFIG_NAME); // 优先使用zoo.cfg配置 
  7.   if (inputStream != null) {  
  8.     try {  
  9.       return parseZooCfg(conf, inputStream);  
  10.     } catch (IOException e) {  
  11.       LOG.warn("Cannot read " + HConstants.ZOOKEEPER_CONFIG_NAME +  
  12.                ", loading from XML files", e);  
  13.     }  
  14.   }  
  15.  
    // 在zoo.cfg配置加载失败的情况下再使用hbase的配置文件中指定的配置项
  16.   // Otherwise, use the configuration options from HBase's XML files.  
  17.   Properties zkProperties = new Properties();  
  18.  
  19.   // Directly map all of the hbase.zookeeper.property.KEY properties.  
  20.   for (Entry<String, String> entry : conf) {  
  21.     String key = entry.getKey();  
  22.     if (key.startsWith(ZK_CFG_PROPERTY)) {  
  23.       String zkKey = key.substring(ZK_CFG_PROPERTY_SIZE);  
  24.       String value = entry.getValue();  
  25.       // If the value has variables substitutions, need to do a get.  
  26.       if (value.contains(VARIABLE_START)) {  
  27.         value = conf.get(key);  
  28.       }  
  29.       zkProperties.put(zkKey, value);  
  30.     }  
  31.   }  
  32.  
  33.   // If clientPort is not set, assign the default  
  34.   if (zkProperties.getProperty(ZK_CLIENT_PORT_KEY) == null) {  
  35.     zkProperties.put(ZK_CLIENT_PORT_KEY,  
  36.                      HConstants.DEFAULT_ZOOKEPER_CLIENT_PORT);  
  37.   }  
  38.  
  39.   // Create the server.X properties.  
  40.   int peerPort = conf.getInt("hbase.zookeeper.peerport", 2888);  
  41.   int leaderPort = conf.getInt("hbase.zookeeper.leaderport", 3888);  
  42.  
  43.   final String[] serverHosts = conf.getStrings(HConstants.ZOOKEEPER_QUORUM,  
  44.                                                "localhost");  
  45.   for (int i = 0; i < serverHosts.length; ++i) {  
  46.     String serverHost = serverHosts[i];  
  47.     String address = serverHost + ":" + peerPort + ":" + leaderPort;  
  48.     String key = "server." + i;  
  49.     zkProperties.put(key, address);  
  50.   }  
  51.  
  52.   return zkProperties;  

加载过程主要是先从CLASSPATH中寻找zoo.cfg的配置文件, 没有再使用hbase的配置项,有一个优先级关系, 需要注意, 否则,在zoo.cfg配置文件存在的情况下, 再怎么修改hbase配置文件否无济于事.

2. 连上zookeeper后会监控哪些节点?
   
HTable连上zookeeper后就会监控一些节点, 以期获取HMaster, HRegionServer等信息, 通过org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher类的setNodeNames方法可以看出:

  1. /**  
  2.  * Set the local variable node names using the specified configuration.  
  3.  */  
  4. private void setNodeNames(Configuration conf) {  
  5.   baseZNode = conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT,  
  6.       HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT);  
  7.   rootServerZNode = ZKUtil.joinZNode(baseZNode,  
  8.       conf.get("zookeeper.znode.rootserver", "root-region-server"));  
  9.   rsZNode = ZKUtil.joinZNode(baseZNode,  
  10.       conf.get("zookeeper.znode.rs", "rs"));  
  11.   masterAddressZNode = ZKUtil.joinZNode(baseZNode,  
  12.       conf.get("zookeeper.znode.master", "master"));  
  13.   clusterStateZNode = ZKUtil.joinZNode(baseZNode,  
  14.       conf.get("zookeeper.znode.state", "shutdown"));  
  15.   assignmentZNode = ZKUtil.joinZNode(baseZNode,  
  16.       conf.get("zookeeper.znode.unassigned", "unassigned"));  
  17.   tableZNode = ZKUtil.joinZNode(baseZNode,  
  18.       conf.get("zookeeper.znode.tableEnableDisable", "table"));  

监控的节点有:
/hbase/master
/hbase/root-region-server
/hbase/rs
/hbase/shutdown
/hbase/unassigned
/hbase/table

接下来验证下zookeeper中是否生成了这些节点,
zkCli -server 192.168.203.129:2181

  1. [zk: 192.168.203.129:2181(CONNECTED) 0]  
  2. [zk: 192.168.203.129:2181(CONNECTED) 0] ls /  
  3. [hbase, zookeeper]  
  4. [zk: 192.168.203.129:2181(CONNECTED) 1] ls /hbase  
  5. [root-region-server, rs, table, unassigned, master, shutdown]  
  6. [zk: 192.168.203.129:2181(CONNECTED) 2] 

通过zookeeper客户端可以确认zookeeper中确实创建了上述六个节点