当zookeeper的状态自动更改时,Watches和Ephemeral节点不起作用?

时间:2013-11-24 05:25:14

标签: python apache-zookeeper watch kazoo

我有一个非常奇怪的Python Kazoo库案例。我在下面的代码中所做的是 -

一旦我使用kazoo库连接到Zookeeper,我创建一个短暂的节点,然后在其他节点上监视,然后我继续在无限循环中继续运行程序..我还添加了一个监听器Zookeeper也将监视状态。

一切对我来说都很好,短暂的节点已经启动,看我的znode也工作得很好......

有时候,由于连接中断或丢失,我看到很奇怪的行为。正如我上面提到的,我已经向zookeeper添加了一个监听器,它将监视状态,我也有一个打印语句。我总是看到,那些打印语句被打印为LostSuspendedConnected,我相信由于连接中断,之后我的短暂节点消失了,我对znode的监视也不起作用。

以下是我的代码,它永远运行 -

#!/usr/bin/python

from kazoo.client import KazooClient
from kazoo.client import KazooState
from kazoo.protocol.states import EventType


def watch_host(event):
    print event


def my_listener(state):
    if state == KazooState.LOST:
    # Register somewhere that the session was lost
        print "Lost"
    elif state == KazooState.SUSPENDED:
    # Handle being disconnected from Zookeeper
        print "Suspended"
    else:
    # Handle being connected/reconnected to Zookeeper
    # what are we supposed to do here?
    print "Being Connected/Reconnected"


zk = KazooClient(hosts='127.0.0.1:2181')
zk.start()

zk.add_listener(my_listener)

# start an ephemeral node
zk.create("/my/example/h0", b"some value", None, True)

# put a watch on my znode
children = zk.get_children("/my/example/test1", watch=watch_host)


while True:
    time.sleep(5)

有没有办法克服这个问题?每当我的Zookeeper状态更改为LostSuspendedConnected时,我都希望这样。我希望通过再次创建它来获得我的短暂节点(如果这是正确的方法)并且我在znode上的监视也始终正常工作。

因为我将永远运行我的程序,所以无论出于何种原因,如果Zookeeper状态由于连接中断而发生变化并且它自动再次连接回来,那么我需要确保我的短暂节点也已启动并且我的手表在znode上也开始自动工作..

目前我的短暂死亡,如果州自动改变,手表也不起作用..

知道如何克服这个问题吗?

2 个答案:

答案 0 :(得分:6)

这是事情,当连接状态发生变化时,你的观察者也会被触发。有一个事件发给了守望者。它可以是nodeDataChanged或nodeChildrenChanged。但是,由于当您的会话终止或存在连接问题时,您无法收到您感兴趣的事件的通知,因此您的观察者将收到有关这些会话问题的通知。我相信这个事件的类型是“无”。

来自http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#ch_zkWatches

关于手表的事项

  • 手表是一次触发;如果你得到一个你想要的观看活动 要获得未来更改的通知,您必须设置另一个手表。
  • 因为手表是一次触发并且之间存在延迟 获得活动并发送新请求以获得您无法获得的手表 可靠地查看ZooKeeper中节点发生的每个更改。是 准备处理znode多次更改的情况 在获取活动和再次设置手表之间。 (你不可以 关心,但至少意识到它可能会发生。)
  • 监视对象或函数/上下文对只会被触发一次 对于给定的通知。例如,如果相同的监视对象是 注册了同一文件的exists和getData调用 然后删除该文件,只调用watch对象 一次带有文件的删除通知。
  • 断开与服务器的连接时(例如,当服务器断开连接时) 失败),在连接之前你不会得到任何手表 重新建立。因此,会话事件将发送给所有人 杰出的手表处理程序。使用会话事件进入保险箱 模式:断开连接时不会接收事件,所以你的 过程应该以该模式保守地行事。

所以,长话短说,你的观察者应该破解事件以查看它是什么类型,并通过进入某种故障转移模式适当地响应None类型。

我通常做的是我的Watcher对象也是听众。当重新连接发生时,我通过重置我的手表来做出回应,确保检查是否存在适当的znodes,并在必要时创建它们。

答案 1 :(得分:5)

我对Python一无所知,但我想我会强调一些关于ZNodes的基本要点 Znodes有两种类型:ephemeralpersistent

  • 创建客户端的会话结束后,ZooKeeper会删除ephemeral znode 创建persistent znode只有在客户端明确删除时才会被删除(不一定是创建它的人)。
  • ephemeral znode永远不会有任何子女关联,甚至不会ephemeral个。
  • 节点上的观察者只触发一次(在Java API版本中),因此您需要重新注册该事件,以便获得节点上未来更新的触发器

在Java版本(Java API)中,如果客户端连接到多个服务器,并且它与连接的服务器断开连接,那么我们会使用KeeperState.Disconnected触发事件,但它会重新尝试并连接到另一台服务器,< strong>在这个时间ephemeral znode和所有手表完好无损,即它们没有被销毁但是一旦调用KeeperState.Expired的事件(当客户端无法与任何服务器建立连接时)在指定的时间内)然后 ephemeral znode被销毁我们必须创建一个新的客户端连接(实例化一个新的ZooKeeper实例)如果我们想要访问整体然后重新建立一切都是节点创建和添加手表。

所以我认为在你的情况下这也可能适用,如Understanding Kazoo States Section

中所述
  

当连接转换为LOST时,Zookeeper将删除已创建的任何短暂节点。这会影响创建短暂节点的所有配方,例如锁定配方。在状态再次转换为CONNECTED之后,需要重新获取锁定。当会话过期或停止客户端连接时,会发生此转换。

希望此信息可以帮助您了解各种状态以及何时重新配置所有状态。