ZooKeeper:Connection Loss/Session Expired

会话

  ZooKeeper客户端和服务端建立Socket长连接之后,服务器端创建一个session,生成一个全局唯一的会话ID(Session ID)。在SESSION_TIMEOUT时间内,服务器会确定客户端是否正常连接(客户端会定时向服务器发送心跳信息,服务器重置下次SESSION_TIMEOUT时间)。因此,在正常情况下,session一直有效,并且ZooKeeper集群所有机器上都保存这个session信息。客户端什么时候向服务器发送心跳消息?
  在创建Session时,需要设置Session Timeout参数,该参数是Zookeeper服务允许一个session在定义它失效之前的时间。如果服务在时间t内不能看到与一个session关联的消息,它将定义这个session失效。如果客户端在1/3 t时间内没有听到任何从服务器过来的消息,它将发送一个心跳消息给服务器。在(2/3)t时间, Zookeeper客户端开始寻找另一个Zookeeper服务器,并且它有另外的(1/3)t的时间寻找。
  因为网络原因或者服务器原因,Socket 断开,客户端尝试重新连接,等到重新连接上,发现之前的session已经不在了,服务器会告诉客户端会话超时,客户端会关闭session,然后开启新的session.。

客户端将连接哪一个服务器?
  在Quorum模式,一个客户端拥有多个服务器可以连接。然而在Standalone模式,它必须尝试有效地连接到那个唯一的服务器。在Quorum模式,会传一个服务器列表到客户端,客户端从中选择一个连接。
  当尝试连接另一个服务器时,很重要的一点是这个服务器的ZooKeeper状态至少要和客户端已经观察到的最近ZooKeeper状态是一样新的。Zookeeper通过在服务中排序更新操作来决定新鲜程度(Freshness)。每一个对Zookeeper布局状态的改动操作相对于所有其它执行的更新操作都是全序的,所以如果一个客户端已经在位置i观察到一个更新,它不能连接一个仅看到i’ < i的服务器。在ZooKeeper的实现中,系统分配给每个更新操作一个事务ID来建立这个顺序。例如客户端因为超时和s1断开连接后,它尝试连接s2,但是s2已经落后了,并不能反应客户端已知的更新。而s3已经看到和客户端一样看到的更新,所以它被安全连接。

异常情况

  在这个会话过程中,用户可能会看到两类异常CONNECTIONLOSS(连接断开)和SESSIONEXPIRED(Session过期)。

连接断开(Connection Loss)

  连接断开(CONNECTIONLOSS)一般发生在网络的闪断或是客户端所连接的服务器挂机的时候。这种情况下,ZooKeeper客户端首先会捕获“连接断开”异常 ——> 获取一个新的ZooKeeper地址 ——> 尝试连接
  整个过程依赖于ZooKeeper客户端自己进行并且使用同一个会话ID,因此发生CONNECTION LOSS时,应用不需要处理,等待ZooKeeper客户端建立新的连接即可。

会话超时(Session Expired)

  Session Expired发生在ZooKeeper客户端与服务器的连接断了,试图连接上新的ZooKeeper机器,但由于耗时过长,超过了SESSION_TIMEOUT 后还没有成功连接上服务器,那么服务器认为这个Session已经结束了(服务器无法确认是因为其它异常原因还是客户端主动结束会话)。由于在ZooKeeper中,很多数据和状态都是和会话绑定的,一旦会话失效,那么ZooKeeper就开始清除和这个会话有关的信息,包括这个会话创建的临时节点和注册的所有Watcher。在这之后,由于网络恢复后,客户端可能会重新连接上服务器,但是服务器会告诉客户端一个异常:Session Expired(会话过期)。此时客户端的状态变成 CLOSED状态,要重新实例ZooKeeper对象,重新操作所有临时数据(包括临时节点和注册Watcher)。
  因此一旦发生Session Expired,存储在ZooKeeper上的所有临时数据与注册的订阅者都会被移除,此时需要重新创建一个ZooKeeper客户端实例,需要自己编码做一些额外的处理。

发布了107 篇原创文章 · 获赞 19 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/ThreeAspects/article/details/103556996