Zookeeper Leader选举实现

项目背景:

web端monitor模块,负责处理实时应用(app)上传的metric信息,但是多台jboss不能重复处理,因此利用Zookeeper leader选举功能,从多台jboss中选出一个leader,负责分发各app给jboss进行metric统计及告警

相关说明:

* Curator 有两种leader选举的recipe, 分别是 LeaderSelector 和 LeaderLatch。
* LeaderSelector : 所有存活的客户端不间断的轮流做 Leader,大同社会
* LeaderLatch : 一旦选举出 Leader,除非有客户端挂掉重新触发选举,否则不会交出领导权

demo说明:

* LeaderLatchE : LeaderLatch 的实现
* LeaderSelectorE : LeaderSelector 的实现

项目中的leader只负责app分发,采用 LeaderLatch 方式即可满足要求

LeaderLatchE

LeaderLatch:一旦选举出Leader,除非有客户端挂掉重新触发选举,否则不会交出领导权。

构建十个待选举实例:Instance,经过 选主 -> 关闭 -> 选主的 过程。

/**
 * 一旦选举出Leader,除非有客户端挂掉重新触发选举,否则不会交出领导权。
 */
public class LeaderLatchE {

    private static String PATH = "/francis/leaderLatch";

    private static final int CLIENT_QTY = 10;

    /**
     * 各实例客户端
     */
    private static final List<CuratorFramework> clients = new ArrayList<>();
    /**
     * 各实例LeaderLatch
     */
    private static final List<LeaderLatch> examples = new ArrayList<>();

    public static void main(String[] args) throws Exception {
        TestingServer server = new TestingServer();

        for (int i = 0; i < CLIENT_QTY; i++) {
            new Thread(new Instance(server, i)).start();
        }

        Thread.sleep(2_000);

        try {
            for (LeaderLatch latch : examples) {
                if (latch.hasLeadership()) {
                    System.err.println("current leader is " + latch.getId() + ", and close it.");
                    latch.close(LeaderLatch.CloseMode.SILENT);
                }
            }
            Thread.sleep(2_000);

            for (LeaderLatch latch : examples) {
                if (latch.hasLeadership()) {
                    System.err.println("current leader is " + latch.getId() + ", and close it.");
                    latch.close(LeaderLatch.CloseMode.SILENT);
                }
            }
        } finally {
            close(server);
        }
    }

    /**
     * 关闭资源(CloseableUtils.closeQuietly只能处理IOException)
     * @param server TestingServer
     */
    private static void close(TestingServer server) throws IOException {
        try {
            for (LeaderLatch latch : examples) {
                if (null != latch.getState()) {
                    CloseableUtils.closeQuietly(latch);
                }
            }
            for (CuratorFramework client : clients) {
                CloseableUtils.closeQuietly(client);
            }
            server.close();
        } catch (IllegalStateException e) {
            // Already closed or has not been started
        }
    }

    /**
     * 待选举的实例
     */
    private static class Instance implements Runnable {

        private TestingServer server;
        /**
         * 实例索引
         */
        private int index;

        Instance(TestingServer server, int index) {
            this.server = server;
            this.index = index;
        }

        @Override
        public void run() {
            try {
                CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new ExponentialBackoffRetry(20000, 3));
                clients.add(client);

                LeaderLatch latch = new LeaderLatch(client, PATH, "Client #" + index);
                latch.addListener(new LeaderLatchListener() {

                    @Override
                    public void isLeader() {
                        System.err.println("I am Leader, index = " + index);
                    }

                    @Override
                    public void notLeader() {
                        System.err.println("I am not Leader, index = " + index);
                    }
                });
                examples.add(latch);

                client.start();
                latch.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

LeaderSelectorE

LeaderSelector:所有存活的客户端不间断的轮流做Leader,大同社会。

/**
 * 所有存活的客户端不间断的轮流做Leader,大同社会
 */
public class LeaderSelectorE {

    private static final String PATH = "/francis/leaderSelector";

    private static final int CLIENT_QTY = 10;

    public static void main(String[] args) throws Exception {
        TestingServer server = new TestingServer();
        try {

            for (int i = 0; i < CLIENT_QTY; i++) {
                new Thread(new Instance(server, i)).start();
            }

            System.err.println("Press enter/return to quit\n");
            new BufferedReader(new InputStreamReader(System.in)).readLine();
        } finally {
            System.err.println("Shutting down...");
            for (LeaderSelectorAdapter exampleClient : examples) {
                CloseableUtils.closeQuietly(exampleClient);
            }
            for (CuratorFramework client : clients) {
                CloseableUtils.closeQuietly(client);
            }
            CloseableUtils.closeQuietly(server);
        }
    }

    private static class LeaderSelectorAdapter extends LeaderSelectorListenerAdapter implements Closeable {
        private final String name;
        private final LeaderSelector leaderSelector;
        private final AtomicInteger leaderCount = new AtomicInteger();

        public LeaderSelectorAdapter(CuratorFramework client, String path, String name) {
            this.name = name;
            leaderSelector = new LeaderSelector(client, path, this);
            leaderSelector.autoRequeue();
        }

        public void start() {
            leaderSelector.start();
        }

        @Override
        public void close() {
            leaderSelector.close();
        }

        @Override
        public void takeLeadership(CuratorFramework client) {
            final int waitSeconds = (int) (5 * Math.random()) + 1;
            System.err.println(name + " is now the leader. Waiting " + waitSeconds + " seconds...");
            System.err.println(name + " has been leader " + leaderCount.getAndIncrement() + " time(s) before.");
            try {
                Thread.sleep(TimeUnit.SECONDS.toMillis(waitSeconds));
            } catch (InterruptedException e) {
                System.err.println(name + " was interrupted.");
                Thread.currentThread().interrupt();
            } finally {
                System.err.println(name + " relinquishing leadership.\n");
            }
            // 出方法同步释放领导权
        }
    }

    /**
     * 各实例客户端
     */
    private static final List<CuratorFramework> clients = new ArrayList<>();
    /**
     * 各实例LeaderSelector
     */
    private static final List<LeaderSelectorAdapter> examples = new ArrayList<>();

    /**
     * 待选举的实例
     */
    private static class Instance implements Runnable {

        private TestingServer server;
        /**
         * 实例索引
         */
        private int index;

        Instance(TestingServer server, int index) {
            this.server = server;
            this.index = index;
        }

        @Override
        public void run() {
            try {
                CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new ExponentialBackoffRetry(20000, 3));
                clients.add(client);

                LeaderSelectorAdapter selectorAdapter = new LeaderSelectorAdapter(client, PATH, "Client #" + index);
                examples.add(selectorAdapter);

                client.start();
                selectorAdapter.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值