利用ZooKeeper开发分布式应用系统案例--服务端与客户端实现
服务端代码:
package cn.edu360.zk.distributesystem; 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; import org.apache.zookeeper.data.Stat; public class TimeQueryServer { ZooKeeper zk = null; //启动zk客户端连接 public void connectZK() throws Exception { zk = new ZooKeeper("hadoop1:2181,hadoop2:2181,hadoop3:2181", 2000, null); } //注册服务器信息 public void registerServerInfo(String hostname,String port) throws Exception, InterruptedException { /* * 先判断注册节点是否存在,如果不存在,则创建 */ Stat stat = zk.exists("/servers", false); if(stat == null) { zk.create("/servers", null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } //注册服务器数据到zk的约定注册节点下 String create = zk.create("/servers/server", (hostname + ":" + port).getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); System.out.println(hostname + "服务器向zk注册信息成功,注册的节点为:" + create); } //启动业务线程开始处理业务 public static void main(String[] args) throws Exception, Exception { TimeQueryServer timeQueryServer = new TimeQueryServer(); //启动zk客户端连接 timeQueryServer.connectZK(); //注册服务器信息 timeQueryServer.registerServerInfo(args[0], args[1]); //启动业务线程开始处理业务 new TimeQueryService(Integer.parseInt(args[1])).start(); } }
服务端线程代码:
package cn.edu360.zk.distributesystem; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; public class TimeQueryService extends Thread{ int port = 0; public TimeQueryService(int port) { this.port = port; } @Override public void run() { try { ServerSocket ss = new ServerSocket(port); System.out.println("业务线程已绑定端口"+ port + "准备接受消费端请求了..."); while(true) { Socket sc = ss.accept(); InputStream inputStream = sc.getInputStream(); OutputStream outputStream = sc.getOutputStream(); outputStream.write(new Date().toString().getBytes()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
客户端代码:
package cn.edu360.zk.distributesystem; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.EventType; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooKeeper; public class Consumer { //定义一个list用于存放最新的在线服务器列表 private volatile ArrayList<String> onlineServers = new ArrayList<String>(); //构造zk连接对象 ZooKeeper zk = null; public void connectZK() throws Exception { zk = new ZooKeeper("hadoop1:2181,hadoop2:2181,hadoop3:2181", 2000, new Watcher() { @Override public void process(WatchedEvent event) { if(event.getState() == KeeperState.SyncConnected && event.getType() == EventType.NodeChildrenChanged) { try { //事件回调逻辑中,再次查询zk上的在线服务器节点即可,查询逻辑中又再次注册子节点事件监听。 getOnlineServers(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }); } //查询在线服务器列表 public void getOnlineServers() throws Exception, InterruptedException { List<String> children = zk.getChildren("/servers", true); ArrayList<String> list = new ArrayList<String>(); for (String child : children) { byte[] data = zk.getData("/servers/"+child, false, null); String serverInfo = new String(data); list.add(serverInfo); } onlineServers = list; System.out.println("查询了一次zk,当前在线的服务器有:"+list); } public void sendRequest() throws Exception { Random random = new Random(); while(true) { try { //挑选一台当前在线的服务器 int nextInt = random.nextInt(onlineServers.size()); String server = onlineServers.get(nextInt); String hostname = server.split(":")[0]; int port = Integer.parseInt(server.split(":")[1]); System.out.println("本次请求挑选的服务器为:" + server); Socket socket = new Socket(hostname, port); OutputStream outputStream = socket.getOutputStream(); outputStream.write("haha".getBytes()); outputStream.flush(); InputStream inputStream = socket.getInputStream(); byte[] buf = new byte[256]; int read = inputStream.read(buf); System.out.println("服务器相应的时间为" + new String(buf,0,read)); outputStream.close(); inputStream.close(); socket.close(); Thread.sleep(2000); }catch(Exception e) { e.printStackTrace(); } } } public static void main(String[] args) throws Exception { Consumer consumer = new Consumer(); //构造zk连接对象 consumer.connectZK(); //查询在线服务器列表 consumer.getOnlineServers(); //处理业务(向一台服务器发送时间查询请求) consumer.sendRequest(); } }