Curator provides a very good implementation of some application scenarios of ZK, and there are many extensions, which are in line with the ZK usage specification
Its main components are:
- Recipes , a series of recipe implementations for ZooKeeper, based on Curator Framework.
- Framework , which encapsulates a large number of ZooKeeper common API operations, reduces the difficulty of use, adds some new features based on Zookeeper, manages ZooKeeper links, and automatically relinks when links are lost.
- Utilities , some ZooKeeper operation tool classes including ZK's cluster test tool path generation are very useful, under the Curator-Client package org.apache.curator.utils.
- Client , ZooKeeper's client API encapsulation, replaces the official ZooKeeper class, solves some tedious and low-level processing, and provides some tool classes.
- Errors , exception handling, connection exceptions, etc.
- Extensions , the extension implementation of curator-recipes, split into curator-:stuck_out_tongue_closed_eyes:iscovery and curator-:stuck_out_tongue_closed_eyes:iscovery-server to provide RESTful-based Recipes WEB service.
Download the jar package
// https://mvnrepository.com/artifact/org.apache.curator/curator-framework
compile group: 'org.apache.curator', name: 'curator-framework', version: '2.11.1'
compile group: 'org.apache.curator', name: 'curator-client', version: '2.11.1'
compile group: 'org.apache.curator', name: 'curator-recipes', version: '2.11.1'
compile group: 'org.apache.curator', name: 'curator-test', version: '2.11.1'
Code:
package org.gjp;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.leader.LeaderLatch;
import org.apache.curator.framework.recipes.leader.LeaderLatch.CloseMode;
import org.apache.curator.framework.recipes.leader.LeaderLatchListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.test.TestingServer;
import org.apache.curator.utils.CloseableUtils;
public class LeaderDemo3 {
public static void main(String[]args) throws Exception{
final List<LeaderLatch> leaders=new ArrayList<LeaderLatch>();
final List<CuratorFramework> clients=new ArrayList<CuratorFramework>();
final TestingServer server=new TestingServer();
try{
for(int i=0;i<10;i++){
//Create a mock client
CuratorFramework client=CuratorFrameworkFactory.newClient("127.0.0.1:2181",
new ExponentialBackoffRetry(20000,3));
clients.add(client);
//Leader election Note that the path of each client must be the same to be in the same group
final LeaderLatch leader=new LeaderLatch(client,"/zkpath2","clent"+i);
leader.addListener(new LeaderLatchListener(){
//Execute when obtaining leader permission
public void isLeader() {
System.out.println(leader.getId()+" ;I am Leader");
//The length of the leader permission
try {
final int waitSeconds = (int)(5 * Math.random()) + 1;
Thread.sleep(TimeUnit.SECONDS.toMillis(waitSeconds));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
//Simulate to give up leader permissions
if(leader !=null){
try {
//Close is to notify all clients
leader.close(CloseMode.NOTIFY_LEADER);
} catch (IOException e) {
e.printStackTrace ();
}
}
}
//Execute when leader permission
public void notLeader() {
System.out.println(leader.getId()+" I am not Leader");
}});
leaders.add(leader);
// client start
client.start();
try {
//LeaderLatch must be started: leaderLatch.start(); Once started, LeaderLatch will negotiate with other LeaderLatch using the same latch path, and then randomly select one of them as the leader
leader.start();
} catch (Exception e) {
e.printStackTrace ();
}
}
Thread.sleep(Integer.MAX_VALUE);
}finally{
for(CuratorFramework client:clients){
CloseableUtils.closeQuietly(client);
}
for(LeaderLatch leader:leaders){
CloseableUtils.closeQuietly(leader);
}
CloseableUtils.closeQuietly(server);
}
Thread.sleep(Integer.MAX_VALUE);
}
}
operation result: