Dynamic Sensing of Distributed Server Up and Down-line Function by zookeeper
Business Description
- In a distributed system, the master node can have more than one, which can be dynamically uploaded and downloaded. Any client can sense the upload and downline of the master server in real time. When the primary node is offline, the client receives notification and updates the host information of the primary node that is still online, which can prevent the client from making requests to the node that has been suspended.
Implementation of Server-side
To accomplish the above functions, we can imagine that we can accomplish it through zookeeper's transient nodes. When the server starts up, we connect to zookeeper and register a transient node with it. When the server goes down unexpectedly, the node will also be deleted, so that the client can access all registered nodes'information, which is still working normally. The primary node.
-
The server-side code is as follows:
import java.io.IOException; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; public class ClusterServer { //Zookeeper's ip and port, where zookeeper is a cluster private String ZK_SERVER_LIST = "mini1:2181,mini2:2181,mini3:2181"; //Set timeout time, when the primary node does not respond after 2s, it will be recognized that the node has been hung up. private static final int sessionTimeout = 2000; //All registered node information is available under / servers for easy management private String SERVER_DIR = "/servers"; private ZooKeeper zk; public void connect() throws IOException { zk = new ZooKeeper(ZK_SERVER_LIST, sessionTimeout, new Watcher() { //Called when the zookeeper server cluster is disconnected @Override public void process(WatchedEvent event) { // TODO Auto-generated method stub System.out.println(event.toString()); } }); } public void register(String hontname) throws IOException, KeeperException, InterruptedException { //Create a transient numbered node so that it will be deleted after the node is offline String result = zk.create(SERVER_DIR+"/server", hontname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); System.out.println("Create results:"+result); } public void diy(){ System.out.println("just do it"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) throws IOException, KeeperException, InterruptedException { ClusterServer server =new ClusterServer(); server.connect(); server.register(args[0]); server.diy(); } }
The host information of the current master node is registered in zookeeper to the server when the program starts.
The hostname here could have been dynamically acquired through the java api, but it was omitted for the convenience of experiments.
Implementation of Client
What the client needs is to get the normal working master node and when the master node changes, it can receive information to get the latest normal working master node. So we can monitor the sub-node information under servers.
-
code implementation
import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; public class ClusterClient { private String ZK_SERVER_LIST = "mini1:2181,mini2:2181,mini3:2181"; private static final int sessionTimeout = 2000; private String SERVER_DIR = "/servers"; private ZooKeeper zk; private List<String> servers=new ArrayList<>(); public void connect() throws IOException { zk = new ZooKeeper(ZK_SERVER_LIST, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent event) { System.out.println(event.toString()); try { //After receiving the notification, the server is monitored again. getServerList(); System.out.println(servers); } catch (KeeperException | InterruptedException e) { } } }); } //Get the list of servers and set listeners public void getServerList() throws KeeperException, InterruptedException{ List<String> nodeList = zk.getChildren(SERVER_DIR,true); servers.clear(); for(String node:nodeList){ byte []data = zk.getData(SERVER_DIR+"/"+node, false, null); String hostName = new String(data); servers.add(hostName); } } //Do what you love to do while fulfilling the function of the guardian process public void diy(){ new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub while (true){ } } }).start();; } public static void main(String[] args) throws IOException, KeeperException, InterruptedException { ClusterClient client =new ClusterClient(); client.connect(); client.getServerList(); client.diy(); } }
test
We can run server programs on multiple terminals to simulate multiple master nodes and shut down the terminal directly to simulate the downtime of the master node.
-
The experimental results are as follows (when we add nodes dynamically):
-
All required jar packages are available in zookeeper's decompression pack. Or directly in my github It has code and jar packages.