ZooKeeper集群中的跟随者对客户端请求的处理流程解读(一)

jopen 5年前

在ZooKeeper中QuorumPeer这个类是整个集群的抽象,代表着ZooKeeper的整个集群、其关联着ZooKeeper集群的重要信息,包括集群状态、当前ZK节点的状态、当前ZK节点编号(myid)、数据存储实例(ZKDATABASE)等等。同时QuorumPeer扩展了Thread类,因此在ZooKeeper运行的过程中,QuorumPeer实例是以独立的线程方式运行的。


QuorumPeer线程实例会在主程序体里面循环判断当前集群的状态,这包括下面几种状态:LOOKING(集群正在处于领导者选举的状态)、LEADING(当前节点处于领导者的状态)、 FOLLOWING(当前节点处于跟随者的状态)、OBSERVING(当前节点处于观察者的状态)。


本文主要是介绍跟随者对客户端请求处理链的解读,因此我们在这里只关心当前节点处于跟随者状态的时候的程序入口。看下code:

      case FOLLOWING:                      try {                          LOG.info("FOLLOWING");                          setFollower(makeFollower(logFactory));                          follower.followLeader();                      } catch (Exception e) {                          LOG.warn("Unexpected exception",e);                      } finally {                          follower.shutdown();                          setFollower(null);                          setPeerState(ServerState.LOOKING);                      }                      break;

当ZooKeeper集群结束领导者选举状态之后,如果当前节点判断选举结束当前节点没有被选中,而只能充当跟随者的时候,程序进入上边这个分支,ZooKeepr集群开始构造跟随者实例,即makeFollower方法。makeFollower方法做的事情是根据FollowerZooKeeperServer实例、日志工厂实例和 ZooKeeper的数据存储实例来构造Follower实例,并把Follower实例传递给当前集群QuorumPeer的follower属性来进行关联。

    protected Follower makeFollower(FileTxnSnapLog logFactory) throws IOException {          return new Follower(this, new FollowerZooKeeperServer(logFactory,                   this,new ZooKeeperServer.BasicDataTreeBuilder(), this.zkDb));      }

跟随者实例构造完成之后就进入了 followLeader阶段,也就是跟随领导者的阶段,followLeader方法是Follower接口定义的行为。先简单描述一下 followLeader要做的事情:首先建立和领导者的连接,向领导者同步数据,这里跟随者对领导者的通信数据处理方法主要是 processPacket。然而发现这里的code和客户端的请求并没有毛的关系,那么跟随者对客户端开放的服务哪里去了呢?还记得上面构造跟随者传入的FollowerZooKeeperServer实例吗。


首先看看syncWithLeader这个方法,表面上它是和领导者同步数据的意思,事实上它偷偷的做了很多事情。


首先从领导者读取一个数据包,这个包可能是下面几种类型的命令:

DIFF:领导者发起DIFF命令

SNAP:领导者发起的SNAP命令,跟随者接收到这个命令后会清空本地的ZK数据库,同步领导者的数据。

TRUNC:领导者发起的TRUNC命令,跟随者接收到这个命令之后会根据本地的日志截断数据,到领导者的最新数据处。


完了之后跟随者将zxid设置为领导者相同的zxid,然后建立会话跟踪。


接下来跟随者开始接收领导者其他命令,包括PROPOSAL、COMMIT、UPTODATE、INFORM和NEWLEADER,这也是跟随者和领导者同步的过程中要做的事情。


PROPOSAL:跟随者接收到PROPOSAL命令的时候会将领导者的提议放入未提交“口袋”。


COMMIT:命令会使得跟随者提交之前未提交的提议,当然需要发生在跟随者和领导者同步镜像数据之后,否则还是将提议放入未提交的口袋,UPTODATE表示跟随者和领导者已经同步数据完成,开始进入新的阶段。


INFORM:这个跟观察者相关的,这里先不介绍。


UPTODATE:表示领导者已经和跟随者同步完成、跟随者可以开始接客。。。


NEWLEADER:表示要换领导者了、开启新的时代。


UPTODATE完了之后跟随者会处理未提交和需要提交的提议,未提交的提议需要记录日志等待领导者的COMMIT命令,需要提交的提议跟随者将他写入ZKDatabase。


接下来跟随者要做的事主要是保持和领导者的通信和对客户端请求的接受和处理,下篇文章主再继续介绍跟随者对客户端请求的处理流程。

来自:http://jvmplus.duapp.com/