项目背景:
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();
}
}
}
}