private RegionServerInfo getServerInfo(ServerName serverName)
    throws KeeperException, IOException {
    String nodePath = watcher.getZNodePaths().getRsPath(serverName);
    byte[] data;
    try {
      data = ZKUtil.getData(watcher, nodePath);
    } catch (InterruptedException e) {
      throw (InterruptedIOException) new InterruptedIOException().initCause(e);
    }
    if (data == null) {
      // we should receive a children changed event later and then we will expire it, so we still
      // need to add it to the region server set.
      LOG.warn("Server node {} does not exist, already dead?", serverName);
      return null;
    }
    if (data.length == 0 || !ProtobufUtil.isPBMagicPrefix(data)) {
      // this should not happen actually, unless we have bugs or someone has messed zk up.
      LOG.warn("Invalid data for region server node {} on zookeeper, data length = {}", serverName,
        data.length);
      return null;
    }
    RegionServerInfo.Builder builder = RegionServerInfo.newBuilder();
    int magicLen = ProtobufUtil.lengthOfPBMagic();
    ProtobufUtil.mergeFrom(builder, data, magicLen, data.length - magicLen);
    return builder.build();
  }
Tracks the online region servers via ZK.
<p/>
Handling of new RSs checking in is done via RPC. This class is only responsible for watching for
expired nodes. It handles listening for changes in the RS node list. The only exception is when
master restart, we will use the list fetched from zk to construct the initial set of live region
servers.
<p/>
If an RS node gets deleted, this automatically handles calling of
{@link ServerManager#expireServer(ServerName)}
hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionServerTracker.java