上一篇主要简单的讲述了ZooKeeper是如何处理来自客户端的写请求的。本文主要集中讨论ZooKeeper客户端节点发生故障的处理情况。若ZooKeeper客户端节点发生故障时,他正处于空闲状态,则按照session失效处理。而复杂的情况是ZooKeeper客户端节点发生故障是,他正在等待ZooKeeper服务器端的请求响应。下面将对ZooKeeper客户端节点发生故障的时机进行详细的分类讨论。

     但是在此之前,我还想简单的介绍一下ZooKeeper中session的概念。我们知道ZooKeeper允许客户端创建两种类型的节点:persistent、ephemeral,ephemeral类型的节点是与创建它的客户端一起共存亡的。那么这中间就有问题,ZooKeeper是如何知道客户端还存不存在呢?ZooKeeper是使用session来解决这个问题的,这也是为什么我们在客户端创建ZooKeeper实例时需要传入一个sessionout的参数。当客户端与Follower连接时,实际上是成功创建了一个session,Follower和Leader都保存了这个session信息(实际上Session的建立也是需要Leader同意的)。一方面,客户端会定期的向Follower发送Ping包来告诉这个Follower我还活着;另一方面,Leader也会定期向Follower发送ping包,一则检测它的Follower们是否至少有超过一半还活着,二则Follower们返回他们各自正在服务的客户端(未超时的session),来告诉Leader那些客户端还活着,这样Leader就可以删除那些客户端已经不存在的ephemeral类型的节点。ok,关于这个session问题我们先暂时讨论到这里,下面我们来看看当正在工作的客户端节点发生故障的,ZooKeeper系统是如何来处理的吧。

    1.Follower在第2步时若没有发现客户端已经发生了故障,则他会进行第2步,否则,他将会丢弃该客户端的请求包。

    2.Leader在第3步时还没有发现客户端已经发生了故障,那么后面的第4、5步都会顺利执行。对于第6步,若此时Follower已经发现了该客户端已发生故障,则它不会向客户端发送响应包,而直接从FinalRequestProcessor处理器中返回;若此时Follower还没有发现该客户端已发生故障,则FinalRequestProcessor会将响应包交给对应的NIOServerCnxn,而NIOServerCnxn在发送该响应包时,会抛出异常,但并没有对该异常做任何处理。

    3.Leader在第3步时发现了客户端已经发生了故障,那么后面的第4、5步都会顺利执行,只不过此时的操作类型就是OpCode.error,然后直接从FinalRequestProcessor处理器中返回,而不会发生第6步了。

    4.从上面的分析我们可以看出,第4、5步并不会收到客户端是否发生故障的影响。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐