【问题标题】:Watches and Ephemeral node doesn't work when state of zookeeper changes automatically?当 zookeeper 状态自动更改时,Watches 和 Ephemeral 节点不起作用?
【发布时间】:2013-12-08 21:37:20
【问题描述】:

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

一旦我使用 kazoo 库连接到 Zookeeper,我就创建了一个临时节点,然后监视其他节点,然后我继续在无限循环中永远运行程序。我还添加了一个监听器Zookeeper 也会监控状态。

对我来说一切都很好,临时节点已经启动,在我的 znode 上观察也很好......

有时,由于连接中断或断开,我会看到非常奇怪的行为。正如我上面提到的,我已经向 zookeeper 添加了一个监听器,它将监视状态,我也有一个 print 语句。我总是看到,那些 print 语句被打印为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 上的手表也开始自动工作..

目前,如果状态自动更改,我的短暂死机和手表也不起作用..

知道如何解决这个问题吗?

【问题讨论】:

  • 这很奇怪,但Lost -> 'Suspended' 转换似乎无效。您看到Lost -> Suspended -> Connected 的转换顺序是否正确?
  • 你不能在你知道你已经连接或重新连接的my_listener 的分支中创建临时节点吗?听起来您希望每次连接/重新连接时都创建临时节点,而不仅仅是在初始连接时 - 但您的代码只执行后者。

标签: python apache-zookeeper watch kazoo


【解决方案1】:

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

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

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

所以我认为在你的情况下这也可能适用,正如Understanding Kazoo States Section 中提到的那样

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

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

【讨论】:

  • 断开连接和过期事件之间的时间间隔是多少?
【解决方案2】:

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

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

关于手表的注意事项

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多