Часы и эфемерный узел не работают, когда состояние зоопарка меняется автоматически?

У меня очень странный случай с библиотекой Python Kazoo. Что я делаю в своем коде ниже:

Как только я подключаюсь к Zookeeper с помощью библиотеки kazoo, я создаю эфемерный узел, а затем наблюдаю за каким-то другим узлом, а затем продолжаю запускать программу вечно в бесконечном цикле. Я также добавил прослушиватель в Zookeeper. который также будет следить за состоянием.

У меня все работает отлично, эфемерный узел работает, часы на моем znode тоже работают нормально...

Иногда я наблюдаю довольно странное поведение из-за разрывов или разрывов соединения. Как я упоминал выше, я добавил слушателя в zookeeper, который будет отслеживать состояние, а также у меня есть оператор печати. ​​Я всегда вижу, что эти операторы печати распечатываются как Lost, Suspended, Connected, я полагаю, из-за разрывов соединения и после этого мои эфемерные ноды умирают и мои часы на зноде тоже не работают.

Ниже мой код, который работает вечно -

#!/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 менялось на Lost, Suspended или Connected. Я хочу, чтобы мой эфемерный узел работал, создав его снова (если это правильный подход), и мои часы на znode также всегда будут работать.

Поскольку я буду запускать свою программу всегда, поэтому по какой-то причине, если состояние Zookeeper изменится из-за прерывания соединения, и оно снова автоматически подключится, мне нужно убедиться, что мой эфемерный узел также работает, и мои часы на znode также начинают работать автоматически..

В настоящее время мой эфемер умирает, и часы также не работают, если состояние меняется автоматически..

Любая идея, как преодолеть эту проблему?


person arsenal    schedule 24.11.2013    source источник
comment
Странно, но переход Lost -> «Приостановлено» кажется недействительным. Вы видите правильную последовательность переходов Lost -> Suspended -> Connected?   -  person twil    schedule 28.11.2013
comment
Не могли бы вы создать эфемерный узел в ветке my_listener, где, как вы знаете, вы были подключены или повторно подключены? Похоже, вы хотите создавать эфемерный узел каждый раз, когда вы подключаетесь/переподключаетесь, а не только при первоначальном подключении, но ваш код делает только последнее.   -  person matt b    schedule 22.01.2014


Ответы (2)


Вот в чем дело, когда происходит изменение состояния соединения, ваш наблюдатель также срабатывает. Есть Событие, которое дается Наблюдателю. Это может быть что-то вроде nodeDataChanged или nodeChildrenChanged. Однако, поскольку было бы невозможно получить уведомление об интересующем вас событии, когда ваш сеанс завершен или возникла проблема с подключением, ваш наблюдатель получит уведомление об этих проблемах с сеансом. Я считаю, что тип события для этого "Нет".

Из http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#ch_zkWatches

Что следует помнить о часах

  • Часы — это одноразовые триггеры; если вы получаете событие наблюдения и хотите получать уведомления о будущих изменениях, вы должны установить другое наблюдение.
  • Поскольку часы — это одноразовые триггеры, и существует задержка между получением события и отправкой нового запроса на получение часов, вы не можете надежно увидеть каждое изменение, которое происходит с узлом в ZooKeeper. Будьте готовы справиться со случаем, когда znode меняется несколько раз между получением события и повторной установкой часов. (Вам может быть все равно, но, по крайней мере, вы понимаете, что это может произойти.)
  • Объект наблюдения или пара функция/контекст будет запущен только один раз для данного уведомления. Например, если один и тот же объект наблюдения зарегистрирован для файла exists и вызов getData для того же файла, а затем этот файл удаляется, объект наблюдения будет вызываться только один раз с уведомлением об удалении файла.
  • Когда вы отключаетесь от сервера (например, когда сервер выходит из строя), вы не получите никаких часов, пока соединение не будет восстановлено. По этой причине события сеанса отправляются всем незавершенным обработчикам наблюдения. Используйте события сеанса для перехода в безопасный режим: вы не будете получать события при отключении, поэтому ваш процесс должен действовать консервативно в этом режиме.

Короче говоря, ваш наблюдатель должен взломать событие, чтобы увидеть, какого оно типа, и соответствующим образом отреагировать на тип None, перейдя в какой-то аварийный режим.

Что я обычно делаю, так это то, что мои объекты Watcher также являются слушателями. Когда происходит переподключение, я отвечаю, сбрасывая свои часы, проверяя наличие соответствующих узлов и создавая их при необходимости.

person Matthew Daumen    schedule 24.01.2014

Я ничего не знаю о Python, но думаю, что выделю некоторые основные моменты о ZNodes
Znodes бывают двух типов: ephemeral или persistent

  • ephemeral znode удаляется ZooKeeper, как только завершается сеанс создания клиента.
    Однажды созданный persistent znode удаляется только при явном удалении клиентом (не обязательно тем, кто его создал).
  • ephemeral znode никогда не будет иметь детей, даже ephemeral.
  • Наблюдатели на узле запускаются только один раз (в версии Java API), поэтому вам необходимо повторно зарегистрировать событие, чтобы получить триггеры для будущих обновлений на узлах.

В версии Java (Java API), если клиент подключен более чем к одному серверу, и если он отключается от подключенного сервера, мы получаем событие, инициированное с помощью KeeperState.Disconnected, но он повторяет попытку и подключается к другому серверу, между этим временем ephemeral znode и все часы целы, т.е. не уничтожаются, но как только вызывается событие с KeeperState.Expired (когда клиент не может установить соединение ни с одним из серверов в указанное время), то ephemeral znode уничтожается и мы должны создать новое клиентское соединение (создать новый экземпляр ZooKeeper), если мы хотим получить доступ к ансамблю, а затем восстановить все, то есть создание узла и добавление часов.

Поэтому я думаю, что в вашем случае это также может быть применимо, как указано в Раздел о состояниях Kazoo

Когда соединение переходит в состояние LOST, Zookeeper удаляет все созданные эфемерные узлы. Это влияет на все рецепты, которые создают эфемерные узлы, такие как рецепт блокировки. Блокировку необходимо будет повторно получить после того, как состояние снова перейдет в CONNECTED. Этот переход происходит по истечении срока действия сеанса или при прекращении подключения клиентов.

Надеюсь, эта информация поможет вам понять различные состояния и понять, когда нужно все заново настроить.

person dbw    schedule 23.01.2014
comment
Сколько времени проходит между событиями Disconnected и Expired? - person brian beuning; 06.05.2018