ZooKeeper(配置管理)
配置的管理在分布式应用环境中很常见,例如同一个应用系统需要多台 PC Server 运行,但是它们运行的应用系统的某些配置项是相同的,如果要修改这些相同的配置项,那么就必须同时修改每台运行这个应用系统的 PC Server,这样非常麻烦而且容易出错。
像这样的配置信息完全可以交给 Zookeeper 来管理,将配置信息保存在 Zookeeper 的某个目录节点中,然后将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中。

本章主要是分布式环境下zookeeper配置管理,通过举例数据库的配置管理:
主要两个class,SetConfig 主要是对节点设置配置。ConfWatchClient 是节点拉去zookeeper的配置到本地。
package com.sw.config;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooKeeper.States;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
public class SetConfig implements Watcher{
public static final String PATH = "/root/config";// 所要监控的结点
private static ZooKeeper zk;
private String CONF_AUTH = "digest"; //zk client auth
private String CONF_PASSWD = "config:123456"; //zk client password
private final static String URLNode = PATH + "/urlNode";
private final static String userNameNode = PATH + "/userNode";
private final static String passwordNode = PATH + "/passwdNode";
public static void main(String[] args) {
SetConfig setConfig = new SetConfig();
setConfig.setValue();
}
public List<ACL> getAuth() throws NoSuchAlgorithmException{
List<ACL> acls = new ArrayList<ACL>(2);
Id id1 = new Id("digest", DigestAuthenticationProvider.generateDigest("admin:admin"));
ACL acl1 = new ACL(ZooDefs.Perms.ALL, id1);
Id id2 = new Id("digest", DigestAuthenticationProvider.generateDigest("guest:guest"));
ACL acl2 = new ACL(ZooDefs.Perms.READ, id2);
acls.add(acl1);
acls.add(acl2);
return acls;
}
public void setValue(){
String urlStr = "192.168.0.2";
String userStr = "admin";
String passwordStr = "admin";
ZooKeeper zk = this.initZk();
try {
if(zk.exists(PATH, true)==null){
zk.create(PATH, urlStr.getBytes(), getAuth(), CreateMode.PERSISTENT);
}
if(zk.exists(URLNode, true)==null){
zk.create(URLNode, urlStr.getBytes(), getAuth(), CreateMode.PERSISTENT);
}else {
States stat = zk.getState();
zk.setData(URLNode, "1.1.1.1".getBytes(), -1);
}
if(zk.exists(userNameNode, true)==null){
zk.create(userStr, urlStr.getBytes(), getAuth(), CreateMode.PERSISTENT);
}
if(zk.exists(passwordNode, true)==null){
zk.create(passwordStr, urlStr.getBytes(), getAuth(), CreateMode.PERSISTENT);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public ZooKeeper initZk() {
try {
zk = new ZooKeeper("192.168.1.2:4181", 21810,this);
zk.addAuthInfo(CONF_AUTH, CONF_PASSWD.getBytes()); //设置连接权限
} catch (IOException e) {
System.err.println("zk init connect fail" + e.getMessage());
}
return zk;
}
@Override
public void process(WatchedEvent event) {
// 主结点的数据发生改变时
if (event.getType() == EventType.NodeDataChanged) {
System.err.println(event);
}
if (event.getType() == EventType.NodeDeleted){
System.err.println(event);
}
if(event.getType()== EventType.NodeCreated){
System.err.println(event);
}
if(event.getType()== EventType.NodeChildrenChanged){
System.err.println(event);
}
}
}
package com.sw.config; import java.io.IOException; import java.util.List; import org.apache.log4j.Logger; 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.ZooKeeper; import com.sw.WatchClient; public class ConfWatchClient implements Watcher{ private static final Logger logger = Logger.getLogger(WatchClient.class); public static final String PATH = "/root/config";// 所要监控的结点 private static ZooKeeper zk; private static List<String> nodeList;// 所要监控的结点的子结点列表 private String URL = ""; private String userName = ""; private String password = ""; private String CONF_AUTH = "digest"; //zk client auth private String CONF_PASSWD = "config:123456"; //zk client password private final static String URLNode = PATH + "/urlNode"; private final static String userNameNode = PATH + "/userNode"; private final static String passwordNode = PATH + "/passwdNode"; public static void main(String[] args) throws Exception { ConfWatchClient client = new ConfWatchClient(); client.initZk(); client.getConfig(); } public void initConfig(){ try { URL = new String(zk.getData(URLNode, true, null),"utf-8"); userName = new String(zk.getData(userNameNode, true, null),"utf-8"); password = new String(zk.getData(passwordNode, true, null),"utf-8"); System.err.println("URL:"+URL+","+"userName:"+userName+",password:"+password); } catch (Exception e) { e.printStackTrace(); } } public ZooKeeper initZk() { try { zk = new ZooKeeper("192.168.1.2:4181", 21810,this); zk.addAuthInfo(CONF_AUTH, CONF_PASSWD.getBytes()); //设置连接权限 } catch (IOException e) { System.err.println("zk init connect fail" + e.getMessage()); } return zk; } public void getConfig() { try { /** * 持续监控 */ while (true) { try { zk.exists(PATH, this);//所要监控的主结点 nodeList = zk.getChildren(PATH, this); System.err.println(nodeList); Thread.sleep(5000);// sleep一会,减少CUP占用率 } catch (KeeperException | InterruptedException e) { System.err.println(e.getMessage()); } } } catch (Exception e) { e.getStackTrace(); } } public void process(WatchedEvent event) { // 主结点的数据发生改变时 if (event.getType() == EventType.NodeDataChanged) { System.err.println(event); initConfig(); } if (event.getType() == EventType.NodeDeleted){ System.err.println(event); } if(event.getType()== EventType.NodeCreated){ System.err.println(event); } if(event.getType()== EventType.NodeChildrenChanged){ System.err.println(event); initConfig(); } } public String getURL() { return URL; } public void setURL(String uRL) { URL = uRL; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }