通过Zookeeper动态感知服务器上下线[案例]

来源:互联网 发布:js自定义全局函数 编辑:程序博客网 时间:2024/05/16 13:46

主体思路:

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

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

效果:

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


服务器端源码:

package com.zn.zk1;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class DistributedServer {private static final String connectString = "zk01:2181,zk02:2181,zk03:2181";private static final int sessionTimeout = 2000;private static final String parentNode = "/servers";private ZooKeeper zk = null;/** * 模拟服务器上线 * @param args * @throws Exception */public static void main(String[] args) throws Exception {// 获取zk连接DistributedServer server = new DistributedServer();server.getConnect();// 利用zk连接注册服务器信息server.registerServer(args[0]);// 启动业务功能server.handleBussiness(args[0]);}/** * 创建到zk的客户端连接 *  * @throws Exception */public void getConnect() throws Exception {zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {public void process(WatchedEvent event) {// 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)System.out.println(event.getType() + "---" + event.getPath());try {zk.getChildren("/", true);} catch (Exception e) {}}});}/** * 向zk集群注册服务器信息 *  * @param hostname * @throws Exception */public void registerServer(String hostname) throws Exception {//运行时请手动创建父节点/servers//临时的临时的序列化结点String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);System.out.println(hostname + "is online.." + create);}/** * 业务功能 *  * @throws InterruptedException */public void handleBussiness(String hostname) throws InterruptedException {System.out.println(hostname + "start working.....");Thread.sleep(Long.MAX_VALUE);  }}


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

客户端源码:

package com.zn.zk1;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 DistributedClient {private static final String connectString = "zk01:2181,zk02:2181,zk03:2181";private static final int sessionTimeout = 2000;private static final String parentNode = "/servers";/**注意:加volatile的意义何在?---serverList对象在JVM堆中,多线程时会对该对象进行更改,每个线程对该对象操作会 *      copy一个副本到本地线程栈,再对该对象进行修改操作,改完后,再将该对象同步到共享的堆内存中。 *     被volatile修饰的对象则不会被copy到本地线程栈。所有线程看到的该对象是同一个。不会出现多线程问题。 */private volatile List<String> serverList;private ZooKeeper zk = null;public static void main(String[] args) throws Exception {// 获取zk连接DistributedClient client = new DistributedClient();//创建zookeeper连接client.getConnect();// 获取servers的子节点信息(并监听),从中获取服务器信息列表client.getServerList();// 业务线程启动client.handleBussiness();}/** * 业务功能 *  * @throws InterruptedException */public void handleBussiness() throws InterruptedException {System.out.println("client start working.....");Thread.sleep(Long.MAX_VALUE);}/** * 创建到zk的客户端连接 * @throws Exception */public void getConnect() throws Exception {zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {public void process(WatchedEvent event) {// 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)try {//重新更新服务器列表,并且注册了监听getServerList();} catch (Exception e) {}}});}/** * 获取服务器信息列表 *  * @throws Exception */public void getServerList() throws Exception {// 获取服务器子节点信息,并且对父节点进行监听List<String> children = zk.getChildren(parentNode, true);// 先创建一个局部的list来存服务器信息List<String> servers = new ArrayList<String>();for (String child : children) {// child只是子节点的节点名byte[] data = zk.getData(parentNode + "/" + child, false, null);servers.add(new String(data));}// 把servers赋值给成员变量serverList,已提供给各业务线程使用serverList = servers;//打印服务器列表System.out.println(serverList);}}

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

1 0
原创粉丝点击