Curator源码解析(四)ZooKeeper存在的连接问题,curatorzookeeper


都说Curator的连接机制比较牛逼,所以在分析Curator的连接和重试机制之前,我想先搞清楚原生的ZooKeeper的连接存在哪些问题。

下面是我查阅资料总结的结果,转载请注明出处: jiq•钦's technical Blog

Curator虽然提供所谓的高层抽象API来简化了ZooKeeper的使用,但更重要的是封装了管理到ZooKeeper集群的连接以及重试机制的复杂性,下面我们来详细分析一下Curator在这方面都是怎么做的,不过在这之前先要搞清楚ZooKeeper目前在连接方面有哪些问题。



会话建立

当你new出一个ZooKeeper对象的时候,客户端就建立了与ZooKeeper服务端之间的一个Session(注意这个session是线程安全的,即多个线程可以共用一个ZooKeeper实例),这个Session会有一个超时时限,即失效时间,通过ZooKeeper的构造函数传递进去,客户端会不断发送心跳(多久发送一次和设置的会话超时时限有关)到ZooKeeper服务端,以保持与ZooKeeper服务端的有效连接和Session的有效性。

 

连接丢失

如果客户端与服务端的网络断开,或客户端连接的ZooKeeper server挂掉,或者与Server的Session的建立后连接还未建立完成,都会出现CONNECTION_LOSS现象,客户端所有watcher都会收到一个disconnected event,客户端连接状态从CONNECTED变为CONNECTING。

 

自动重连

此时客户端库会自动从ZooKeeper服务器列表中选择一个server来进行重连。

A.  如果重新成功建立与服务端的TCP连接,并且没有超过session的超时时限,那么ZooKeeper客户端将会收到一个SyncConnected event,客户端连接状态就又会变为CONNECTED,连接恢复正常且临时节点和注册的watch事件也不会被删除掉。即使重连在一个很短的时间内完成,也会收到了两个事件。

B.  如果过了很久还是不能重新成功建立与服务端的TCP连接,客户端将会一直保持在disconnected状态,也就永远不会收到Expired event,只会有disconnectedevent(因为事件是来自服务端)。

C.  如果重新成功建立与服务端的TCP连接,但是发现已经超过了session设置的超时时限,那么客户端将会收到一个Expired event,表示会话已经终止SESSION_EXPIRED,此时服务器会将这个客户端注册的所有watcher,以及创建的临时节点全部删除,同时客户端持有的ZooKeeper句柄也会被关闭,唯一能做的就是重建ZooKeeper对象。发生SESSION_EXPIRED的watcher将会看到如下状态转换:

'connected': 会话建立,客户端与ZooKeeper集群正常通信

....client is partitioned from the cluster

'disconnected': 客户端丢失与ZooKeeper集群的连接

....time elapses, 时间逐渐流逝,在'timeout'时限后ZooKeeper集群将会终止这个会话,此时处于disconnected状态的客户端将会什么都看不到。

....time elapses, 时间流逝,客户端重新建立与ZooKeeper集群的连接

'expired': 最终客户端重连到ZooKeeper集群,将会收到expiration 通知

 

连接丢失的处理:

CONNECTION_LOSS意味着客户端和服务器端的TCP连接断开,但是并不意味着请求失败。假如正在执行一个create请求,然后在请求到达服务器以及response返回之前,连接断开,这个create请求就会执行成功,假如在数据包发送到线路之前断开那么create请求就会执行失败。很不幸客户端没办法知道在CONNECTION_LOSS发生后自己的请求是否执行成功,开发人员必须要自己检测是否执行成功,是否需要重试,检测的方法包括检查对应的znode是否存在,或者检测znode节点的值是否已被修改。


会话终止的处理:

SESSION_EXPIRED将会自动关闭ZooKeeper句柄,如果正确操作ZooKeeper集群,会话终止现象很难出现,如果客户端强制关闭一个连接倒是一定会出现这个事件,因为服务器认为客户端已经死掉了。如果真的出现会话失效该如何处理呢?

 

后面文章将会分析看Curator是否已经解决这些问题:

(1)发出请求时CONNECTION_LOSS的处理,是否能够知道发出的请求已经执行成功,若不成功能够重试。

(2)SESSION_EXPIRED时的处理,能否让临时节点和注册的watch不被删除。


相关内容

    暂无相关文章