https://blog.csdn.net/USTC_Zn/article/details/54974982

主体思路:

服务器端:服务器上线、在zookeeper创建 临时的序列化结点

客户端:已启动getchildren 并注册监听 ,获取到当前在线服务器列表。

效果:

客户端能动态感知服务器上下线情况、并获取新的服务器列表

 

服务器端源码:

 

  1. package com.zn.zk1;  
  2.   
  3. import org.apache.zookeeper.CreateMode;  
  4. import org.apache.zookeeper.WatchedEvent;  
  5. import org.apache.zookeeper.Watcher;  
  6. import org.apache.zookeeper.ZooDefs.Ids;  
  7. import org.apache.zookeeper.ZooKeeper;  
  8.   
  9. public class DistributedServer {  
  10.     private static final String connectString = "zk01:2181,zk02:2181,zk03:2181";  
  11.     private static final int sessionTimeout = 2000;  
  12.     private static final String parentNode = "/servers";  
  13.   
  14.     private ZooKeeper zk = null;  
  15.       
  16.       
  17.     /** 
  18.      * 模拟服务器上线 
  19.      * @param args 
  20.      * @throws Exception 
  21.      */  
  22.     public static void main(String[] args) throws Exception {  
  23.   
  24.         // 获取zk连接  
  25.         DistributedServer server = new DistributedServer();  
  26.         server.getConnect();  
  27.   
  28.         // 利用zk连接注册服务器信息  
  29.         server.registerServer(args[0]);  
  30.   
  31.         // 启动业务功能  
  32.         server.handleBussiness(args[0]);  
  33.   
  34.     }  
  35.     /** 
  36.      * 创建到zk的客户端连接 
  37.      *  
  38.      * @throws Exception 
  39.      */  
  40.     public void getConnect() throws Exception {  
  41.   
  42.         zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {  
  43.               
  44.             public void process(WatchedEvent event) {  
  45.                 // 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)  
  46.                 System.out.println(event.getType() + "---" + event.getPath());  
  47.                 try {  
  48.                     zk.getChildren("/", true);  
  49.                 } catch (Exception e) {  
  50.                 }  
  51.             }  
  52.         });  
  53.   
  54.     }  
  55.   
  56.     /** 
  57.      * 向zk集群注册服务器信息 
  58.      *  
  59.      * @param hostname 
  60.      * @throws Exception 
  61.      */  
  62.     public void registerServer(String hostname) throws Exception {  
  63.           
  64.         //运行时请手动创建父节点/servers  
  65.         //临时的临时的序列化结点  
  66.         String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);  
  67.         System.out.println(hostname + "is online.." + create);  
  68.   
  69.     }  
  70.   
  71.     /** 
  72.      * 业务功能 
  73.      *  
  74.      * @throws InterruptedException 
  75.      */  
  76.     public void handleBussiness(String hostname) throws InterruptedException {  
  77.         System.out.println(hostname + "start working.....");  
  78.         Thread.sleep(Long.MAX_VALUE);    
  79.     }  
  80.   
  81.   
  82.   
  83. }  



-----------------------华丽的分界线---------------------

客户端源码:

 

  1. package com.zn.zk1;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.apache.zookeeper.KeeperException;  
  7. import org.apache.zookeeper.WatchedEvent;  
  8. import org.apache.zookeeper.Watcher;  
  9. import org.apache.zookeeper.ZooKeeper;  
  10.   
  11. public class DistributedClient {  
  12.   
  13.     private static final String connectString = "zk01:2181,zk02:2181,zk03:2181";  
  14.     private static final int sessionTimeout = 2000;  
  15.     private static final String parentNode = "/servers";  
  16.       
  17.     /** 注意:加<span style="color:#ff0000;"><strong>volatile的意义</strong></span>何在?---serverList对象在JVM堆中,多线程时会对该对象进行更改,每个线程对该对象操作会 
  18.      *      copy一个副本到本地线程栈,再对该对象进行修改操作,改完后,再将该对象同步到共享的堆内存中。 
  19.      *     被volatile修饰的对象则不会被copy到本地线程栈。所有线程看到的该对象是同一个。不会出现多线程问题。 
  20.      */  
  21.     private volatile List<String> serverList;  
  22.     private ZooKeeper zk = null;  
  23.       
  24.       
  25.     public static void main(String[] args) throws Exception {  
  26.   
  27.         // 获取zk连接  
  28.         DistributedClient client = new DistributedClient();  
  29.           
  30.         //创建zookeeper连接  
  31.         client.getConnect();  
  32.           
  33.         // 获取servers的子节点信息(并监听),从中获取服务器信息列表  
  34.         client.getServerList();  
  35.   
  36.         // 业务线程启动  
  37.         client.handleBussiness();  
  38.           
  39.     }  
  40.   
  41.     /** 
  42.      * 业务功能 
  43.      *  
  44.      * @throws InterruptedException 
  45.      */  
  46.     public void handleBussiness() throws InterruptedException {  
  47.         System.out.println("client start working.....");  
  48.         Thread.sleep(Long.MAX_VALUE);  
  49.     }  
  50.   
  51.     /** 
  52.      * 创建到zk的客户端连接 
  53.      * @throws Exception 
  54.      */  
  55.     public void getConnect() throws Exception {  
  56.   
  57.         zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {  
  58.               
  59.             public void process(WatchedEvent event) {  
  60.                 // 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)  
  61.                 try {  
  62.                     //重新更新服务器列表,并且注册了监听  
  63.                     getServerList();  
  64.   
  65.                 } catch (Exception e) {  
  66.                 }  
  67.             }  
  68.         });  
  69.   
  70.     }  
  71.   
  72.     /** 
  73.      * 获取服务器信息列表 
  74.      *  
  75.      * @throws Exception 
  76.      */  
  77.     public void getServerList() throws Exception {  
  78.   
  79.         // 获取服务器子节点信息,并且对父节点进行监听  
  80.         List<String> children = zk.getChildren(parentNode, true);  
  81.   
  82.         // 先创建一个局部的list来存服务器信息  
  83.         List<String> servers = new ArrayList<String>();  
  84.         for (String child : children) {  
  85.             // child只是子节点的节点名  
  86.             byte[] data = zk.getData(parentNode + "/" + child, false, null);  
  87.             servers.add(new String(data));  
  88.         }  
  89.         // 把servers赋值给成员变量serverList,已提供给各业务线程使用  
  90.         serverList = servers;  
  91.           
  92.         //打印服务器列表  
  93.         System.out.println(serverList);  
  94.           
  95.     }  
  96. }  


最后:可以将两个java文件分别打包、部署到服务器测试、也可以在IDE上测试执行效果。

posted on 2018-04-06 23:10  一天不进步,就是退步  阅读(256)  评论(0编辑  收藏  举报