【问题标题】:Why isn't curator recovering when zookeeper is back online?Zookeeper 重新上线后,为什么馆长没有恢复?
【发布时间】:2021-07-01 18:58:48
【问题描述】:

我有一个针对 Zookeeper 服务器 (v3.7.0) 运行的 CuratorFramework 客户端 (v5.1.0)。如果 Zookeeper 服务器在客户端连接到它时关闭我可以看到连接状态 (带有ConnectionStateListenerSUSPENDED,然后是LOST,然后仅此而已 当服务器重新上线时。

这感觉像是一个非常标准的用例,我一定错过了一些愚蠢的东西,但我永远不能 一旦服务器在线,让客户端再次连接。

我在 Google 上进行了一些搜索,但没有发现有关如何处理丢失状态后恢复的任何有用信息。

我有一个self-contained example 我正在做什么 中的示例代码 CuratorRecoveryTest班级 (在 IDE 而不是 maven 中运行)。它的实质是(从测试类中提取的):

// setup the server and client
server = new TestingServer();

client = newClient(server.getConnectString(), 60000, 15000, new RetryNTimes(1, 250));
client.start();
client.blockUntilConnected();
            
// add the listener
final var stateListener = new StateListener();
stateListener.stateChanged(client, CONNECTED);

// register the listener
client.getConnectionStateListenable().addListener(stateListener);

// verify connection
assertTrue(client.getZookeeperClient().isConnected());

// let things settle
nap(3, "initial settling");

// stop zk
stopServer();
log.info(">>>>>>>>>> STOPPED ZK SERVER");

// let it bake
nap(3, "letting things bake");

// ensure disconnected
assertFalse(client.getZookeeperClient().isConnected());

nap(3, "disconnecting");

// start zk
server.start();
log.info(">>>>>>>>>> STARTED ZK SERVER");

await().atMost(5, MINUTES).until(() -> stateListener.getCurrentState() == CONNECTED || stateListener.getCurrentState() == RECONNECTED);

// NOTE: it never gets here - no state changes after LOST

assertTrue(client.getZookeeperClient().isConnected());

当它运行时,我得到以下输出:

[Thread-0] INFO org.apache.curator.test.TestingZooKeeperMain - Starting server
[Thread-0] WARN org.apache.zookeeper.server.ServerCnxnFactory - maxCnxns is not configured, using default value 0.
[main] INFO org.apache.curator.framework.imps.CuratorFrameworkImpl - Starting
[main] INFO org.apache.curator.framework.imps.CuratorFrameworkImpl - Default schema
[main] WARN demo.CuratorRecoveryTest - CONNECTION-STATE-CHANGE: null --> CONNECTED
[main] DEBUG demo.CuratorRecoveryTest - Taking a 3s nap for initial settling...
[main] DEBUG demo.CuratorRecoveryTest - Done napping for initial settling...
[Curator-ConnectionStateManager-0] WARN demo.CuratorRecoveryTest - CONNECTION-STATE-CHANGE: CONNECTED --> SUSPENDED
[main] INFO demo.CuratorRecoveryTest - >>>>>>>>>> STOPPED ZK SERVER
[main] DEBUG demo.CuratorRecoveryTest - Taking a 3s nap for letting things bake...
[main] DEBUG demo.CuratorRecoveryTest - Done napping for letting things bake...
[main] DEBUG demo.CuratorRecoveryTest - Taking a 3s nap for disconnecting...
[main] DEBUG demo.CuratorRecoveryTest - Done napping for disconnecting...
[main] INFO demo.CuratorRecoveryTest - >>>>>>>>>> STARTED ZK SERVER
[Curator-ConnectionStateManager-0] WARN org.apache.curator.framework.state.ConnectionStateManager - Session timeout has elapsed while SUSPENDED. Injecting a session expiration. Elapsed ms: 20009. Adjusted session timeout ms: 20000
[main-EventThread] WARN org.apache.curator.ConnectionState - Session expired event received
[Curator-ConnectionStateManager-0] WARN demo.CuratorRecoveryTest - CONNECTION-STATE-CHANGE: SUSPENDED --> LOST

当等待条件永远不会发生时,它就会失败。

注意:这也发生在 Curator 和 Zookeeper 的旧版本组合上,因此这不是“前沿”问题。

我错过了什么?

【问题讨论】:

  • 谢谢,我可以用你的 github 代码重现。但是如果我删除server.close,并用restart 替换你的start,它会导致客户端重新连接成功。可能server.close 表示无法再次启动测试服务器。也许将您的原始生产中堆栈跟踪添加到您的问题中?我遇到了您的问题,我怀疑这是由于策展人在使用 ZooKeeper.updateServerList 方法时出现的错误。
  • 此测试旨在模拟 Zookeeper 服务器关闭(可能持续几分钟)然后重新启动 - 不确定您建议的更改是否仍然反映这一点。本身并没有真正的堆栈跟踪,而只是日志中的“无法连接”消息流。我可以用实际的服务器重现它,但很难在测试中展示它。我得研究一下你提到的那个方法。
  • 更新:这似乎是一个红鲱鱼位。当TestingServer 被杀死并重新启动时,它的行为方式与真实服务器不同。当我对标准 ZK 服务器尝试相同的场景时,它在丢失后重新连接良好。我的问题一定来自我的服务代码。我可能会结束这个问题。
  • UPDATE-2:我只是想到测试服务器不适合我的原因是它可能第二次在与第一次不同的端口上启动 - 我必须看看进入这个并发布更新或关闭问题。

标签: java apache-zookeeper apache-curator


【解决方案1】:

我遇到了类似的问题,并得出结论,当 zookeeper 服务器重新启动时,curator 似乎重用了过时的 IP。

this ticket 中概述的方法对我有用。特别是this commit,它添加了一个自定义ZookeeperFactory,它不会重用以前的过期IP,而是使用原始的未解析主机名。

简而言之,在创建馆长时,分配一个自定义的 ZookeeperFactory

CuratorFramework zkClient = CuratorFrameworkFactory
    .builder()
...
    .zookeeperFactory(new ZKClientFactory())

这个ZKClientFactory 从缓存的connectString 创建一个新的Zookeeper

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多