如何使用Curator for Zookeeper高效地使用LeaderElection配方?

joh*_*ohn 11 java distributed apache-zookeeper apache-curator

我正在使用Apache Curator库在Zookeeper上进行领导选举.我将我的应用程序代码部署在各种机器上,我只需要从一台机器执行我的代码,这就是为什么我在动物园管理员上进行领导选举,以便我可以检查我是否是领导者,然后执行此代码.

下面是我的LeaderElectionExecutor类,它确保我每个应用程序都有一个Curator实例

public class LeaderElectionExecutor {

    private ZookeeperClient zookClient;

    private static final String LEADER_NODE = "/testleader";

    private static class Holder {
        static final LeaderElectionExecutor INSTANCE = new LeaderElectionExecutor();
    }

    public static LeaderElectionExecutor getInstance() {
        return Holder.INSTANCE;
    }

    private LeaderElectionExecutor() {
        try {
            String hostname = Utils.getHostName();

            String nodes = "host1:2181,host2:2181;

            zookClient = new ZookeeperClient(nodes, LEADER_NODE, hostname);
            zookClient.start();

            // added sleep specifically for the leader to get selected
            // since I cannot call isLeader method immediately after starting the latch
            TimeUnit.MINUTES.sleep(1);
        } catch (Exception ex) {
            // logging error
            System.exit(1);
        }
    }

    public ZookeeperClient getZookClient() {
        return zookClient;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是我的ZookeeperClient代码 -

// can this class be improved in any ways?
public class ZookeeperClient {

    private CuratorFramework client;
    private String latchPath;
    private String id;
    private LeaderLatch leaderLatch;

    public ZookeeperClient(String connString, String latchPath, String id) {
        client = CuratorFrameworkFactory.newClient(connString, new ExponentialBackoffRetry(1000, Integer.MAX_VALUE));
        this.id = id;
        this.latchPath = latchPath;
    }

    public void start() throws Exception {
        client.start();
        leaderLatch = new LeaderLatch(client, latchPath, id);
        leaderLatch.start();
    }

    public boolean isLeader() {
        return leaderLatch.hasLeadership();
    }

    public Participant currentLeader() throws Exception {
        return leaderLatch.getLeader();
    }

    public void close() throws IOException {
        leaderLatch.close();
        client.close();
    }

    public CuratorFramework getClient() {
        return client;
    }

    public String getLatchPath() {
        return latchPath;
    }

    public String getId() {
        return id;
    }

    public LeaderLatch getLeaderLatch() {
        return leaderLatch;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在我的应用程序中,我正在使用这样的代码 -

public void method01() {
    ZookeeperClient zookClient = LeaderElectionExecutor.getInstance().getZookClient();
    if (zookClient.isLeader()) {
        // do something
    }
}

public void method02() {
    ZookeeperClient zookClient = LeaderElectionExecutor.getInstance().getZookClient();
    if (zookClient.isLeader()) {
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

问题陈述:-

在Curator库中 - isLeader()启动锁存器后立即调用将不起作用.领导者需要时间才能被选中.由于这个原因,我在我的LeaderElectionExecutor代码中添加了1分钟的睡眠,但工作正常,但我想这不是正确的方法.

有没有更好的方法呢?记住这一点,我需要一种方法来检查我是否是领导者然后执行这段代码.我不能在一个方法中做所有事情所以我需要isLeader从不同的类和方法调用方法来检查我是否是领导者然后只执行这段代码.

我使用的是Zookeeper 3.4.5和Curator 1.7.1版本.

小智 0

我以前没有与动物园管理员或馆长合作过,所以对我的回答持保留态度。

设置一个标志。

布尔 isLeaderSelected = false;

在 Latch 的开始处,将标志设置为 false。选择领导者后,将标志设置为 true。

在 isLeader() 函数中:

isLeader(){
while(!isLeaderSelected){} //waits until leader is selected

//do the rest of the function
}
Run Code Online (Sandbox Code Playgroud)

这也是一个相对较老套的解决方法,但它应该允许 isLeader 方法尽快执行。如果它们位于不同的类中,则 getter 应该能够提供 isLeaderSelected。