利用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();
}
}