zookeeper和java实现的统一配置管理和集群节点管理简单案例

1.首先谈谈对zookeeper的认识,以下简称zk

zk做为服务存在,是以三个或者三个以上存在的。服务节点启动不分先后,他会自动选取出leader和follower。

服务奇数个更有利于容错,数据一致性可以谷歌下paxos算法。

 

2.其次是我们自己开发的应用程序app

app以节点树存在与zk上。顶层是父节点,其次是app节点。(节点通过通过ZK api构建,节点上可以存放数据,改变数据)。

 

案例1(APP集群上的统一配置管理)

 

package org.zookeeper;
import java.io.File;
import org.apache.log4j.PropertyConfigurator;
import org.apache.zookeeper.CreateMode;
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.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;


public class AppServer {
private static String groupNode = "sgroup";
private String subNode = "sub";
ZooKeeper zk;
Stat stat = new Stat();

private void updateConfig() throws KeeperException, InterruptedException {
//注意getdata 参数 boolean watch,这里一定要是true,说明每次都要监控节点数据变化的
System.out.println(zk.hashCode()+": current config is:"+new String(zk.getData("/" + groupNode, true, null)));
}

public void connectZookeeper(String address) throws Exception {
//zk集群服务地址
zk = new ZooKeeper("10.15.107.105:2181,10.15.107.42:2181,10.15.107.43:2181", 30*1000, new Watcher() {
public void process(WatchedEvent event) {
if( event.getType().equals(EventType.NodeDataChanged) ){
System.out.println("config is changed");
try {
updateConfig();
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
});
// 在"/sgroup"下创建子节点
// 子节点的类型设置为EPHEMERAL_SEQUENTIAL, 表明这是一个临时节点, 且在子节点的名称后面加上一串数字后缀
// 将server的地址数据关联到新创建的子节点上
Stat s = zk.exists("/" + groupNode, false);
if( s == null  ){
zk.create("/" + groupNode, "".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
zk.setData("/" + groupNode, "origin config".getBytes(), -1);
}
String createdPath = zk.create("/" + groupNode + "/" + subNode,address.getBytes("utf-8"), Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
zk.getData("/" + groupNode, true,null);
System.out.println("create: " + createdPath);
}


/***
* 模拟3个app使用共同配置文件。随后让一个线程去修改配置5次。3个app每次都会收到配置改变的通知。
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//初始化log4j
File f = new File( "user.dir"+ File.separator + "log");
if( !f.exists() ){
f.mkdir();
new File("user.dir" + File.separator + "log"+ File.separator+"land.log");
}
PropertyConfigurator.configureAndWatch(File.separator+ System.getProperty("user.dir") + File.separator + "conf"+ File.separator + "log4j.properties");

String[] hosts = new String[] { "10.15.107.105", "10.15.107.42","10.15.107.43" };
for (int i = 0; i < hosts.length; ++i) {
final AppServer as = new AppServer();
as.connectZookeeper(hosts[i]);
if( i == 2){
new Thread(){
public void run(){
try {
for( int i=0;i<5;++i ){
System.out.println("config begin change");
as.zk.setData("/" + groupNode, (as.zk.hashCode()+" change id:"+Math.random()).getBytes(), -1);
Thread.sleep(3 * 1000);
}
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
Thread.sleep(1 * 1000);
}
Thread.sleep(Long.MAX_VALUE);
}
}

 

 

 

 

 

案例2(实现对APP集群节点监控管理:APP在线和离线能即时通知到监控程序)

APP服务使用案例1的程序,监控程序代码如下:

package org.zookeeper;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.PropertyConfigurator;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;


public class AppClient {
private String groupNode = "sgroup";
private ZooKeeper zk;
private Stat stat = new Stat();
private volatile List serverList;


/**
* 连接zookeeper
*/
public void connectZookeeper() throws Exception {
zk = new ZooKeeper("10.15.107.105:2181,10.15.107.42:2181,10.15.107.43:2181",
30*1000, new Watcher() {
public void process(WatchedEvent event) {
// 如果发生了"/sgroup"节点下的子节点变化事件, 更新server列表, 并重新注册监听
if (event.getType() == EventType.NodeChildrenChanged && ("/" + groupNode).equals(event.getPath())) {
try {
updateServerList();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
updateServerList();
}


/**
* 更新server列表
*/
private void updateServerList() throws Exception {
List newServerList = new ArrayList();


// 获取并监听groupNode的子节点变化
// watch参数为true, 表示监听子节点变化事件.
// 每次都需要重新注册监听, 因为一次注册, 只能监听一次事件, 如果还想继续保持监听, 必须重新注册
List subList = zk.getChildren("/" + groupNode, true);
for (String subNode : subList) {
// 获取每个子节点下关联的server地址
byte[] data = zk.getData("/" + groupNode + "/" + subNode, false,stat);
newServerList.add(new String(data, "utf-8"));
}


// 替换server列表
serverList = newServerList;


System.out.println("current active server address: " + serverList);
}

public static void main(String[] args) throws Exception {
//初始化log4j
File f = new File( "user.dir"+ File.separator + "log");
if( !f.exists() ){
f.mkdir();
new File("user.dir" + File.separator + "log"+ File.separator+"land.log");
}
PropertyConfigurator.configureAndWatch(File.separator+ System.getProperty("user.dir") + File.separator + "conf"+ File.separator + "log4j.properties");

AppClient ac = new AppClient();
ac.connectZookeeper();
Thread.sleep(Long.MAX_VALUE);
}
}

 

你可能感兴趣的:(zookeeper和java实现的统一配置管理和集群节点管理简单案例)