会话
3.2.0版本后支持一个“chroot”后缀,例如:“127.0.0.1:2181/app/a”,它的作用在于使之后的所有路径都变成基于此的相对路径。
zookeeper的会话使用64位的整数来标识。连接创建好时,这个会话ID会连同服务器创建的一个密码一同发给客户端。如果客户端断线,在重新连接到zookeeper的时候,客户端会给出密码和会话ID;所有服务器都可以验证它们的对应情况。这样,便实现了安全。
两个概念比较重要:会话超时时间和tick时间。tick时间一般设置为2000ms,会话超时时间可设为它的2倍到20倍。zookeeper的客户端API会帮助你管理超时重连,而且这个库的设计很高明,“自适应地处理了惊群等情况”。
监视器
zookeeper客户端可以在znode上设置监视器。该znode如果有变化,则对应的监视器被触发,客户端会收到消息,然后这个监视器被移除。三种读操作:getData(), getChildren(), exists(),它们可以可选地在znode上注册监视器——作为本身读数据、读子znode列表、检查存在性的副作用。 监视器有三个要点:
1)只触发一次。
2)向监视者发送。zookeeper保证当znode改变时,客户端不会看到这个改变,直到它设置在这个znode上的监视器被触发,且这个事件已抵达该客户端。这样,不同的客户端在同一时刻可能看到znode的不同形态。举个例子,client_a在znode上设置了监视器A,然后znode更新,但是这个事件被丢失在了网络中,那么client_a再次请求改znode时,将得到最原始的返回结果。这时如果另一个client_b也请求该znode的状态,结果便不同了。另外,如果同一客户端多次向同一znode注册watcher,那么zookeeper保证先注册的watcher会先被递达。
3)getData和exists两个操作设置的是DataWatch,getChildren设置的是ChildrenWatch。例如,一个znode被创建,将会触发它自己的DataWatch,以及其父节点的ChildrenWatch。
监视器只在会话连接到的服务器本地进行维护,这使得监视器本身的设计是非常轻量级的。当客户端连接到新的服务器上时,监视器会被任何会话事件触发(PS,这句是否是说,有些监视器是设置到session上的?)。当客户端重连时,所有之前设置的触发器都会被重设,并视情况被触发。注意,只有1种情况监视器会丢:在客户端断线的时候,它监听的znode被创建出来,但是又删掉了!
watch的语义:created event,deleted event,changed event,;以及child event。
watch可以通过客户端调用removeWathes来移除;当然,如果已无法连接到任何server,客户端也可以设置local flag为真,来单方面消除连接。Java绑定
Java API通过两个包提供功能:org.apache.zookeeper和它的data子包。前者下面的Zookeeper类抽象了一个zookeeper连接,及其连接到的zookeeper集群的视图。它有两个构造函数,其区别在于其中一个额外地需要session id和password两个参数。这样,便可以支持进程失败后从磁盘中恢复会话了。Zookeeper类对象持有两个线程:一个IO线程和一个Event线程。所有IO操作都在IO线程中通过NIO进行,监听器被触发后的回调函数则在Event线程中执行。注意,同步的getData()等数据读写操作也在IO线程中完成。
编程例子
https://github.com/hicqu/zookeeper-learn