一、ZooKeeper的配置管理( Configuration Management)使用场景
配置的管理在分布式应用环境中很常见,例如同一个应用系统需要多台 PC
Server 运行,但是它们运行的应用系统的某些配置项是相同的,如果要修改这些相同的配置项,那么就必须同时修改每台运行这个应用系统的 PC
Server,这样非常麻烦而且容易出错。像这样的配置信息完全可以交给 Zookeeper 来管理,将配置信息保存在 Zookeeper 的某个目录节点中,然后将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中。
二、配置管理结构图
三、实战案例
3.1 工作中有这样的一个场景: 数据库用户名和密码信息放在一个配置文件中,应用读取该配置文件,配置文件信息放入缓存。
若数据库的用户名和密码改变时候,还需要重新加载缓存,比较麻烦,通过ZooKeeper可以轻松完成,当数据库发生变化时自动完成
缓存同步
3.2 模拟程序代码
创建SetConfig.java 写配置文件
创建MyClient.java 读取配置文件和注册watcher到zk上
package example;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
/**
* <p>
* write data to zookeeper
* </p>
*
* @author shenfl
*
*/
public class SetConfig
{
// zk的连接串
private final static String CONNECT_STR = "192.168.2.35:2181" ;
// 连接zk的超时时间
private static final int SESSION_TIMEOUT =
30000;
// 数据库连接
private final static String uRLNode = "10.12.1.1";
private final static String userNameNode = "admin";
private final static String passwdNode = "admin123";
// Auth认证
public static String authType = "digest" ;
public static String authPasswd = "*ik1234" ;
public static void main(String[] args)
{
try {
ZooKeeper zk = new ZooKeeper(CONNECT_STR, SESSION_TIMEOUT , new Watcher()
{
@Override
public void process(WatchedEvent e)
{
System. out.println("
type : " + e.getType()
+ ",path:" + e .getPath());
}
});
zk.addAuthInfo( authType, authPasswd.getBytes());
if(zk .exists("/jfconf" , true)==null){
zk.create( "/jfconf", uRLNode.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT );
}
if (zk .exists("/jfconf/uRLNode" , true)
== null) {
zk.create( "/jfconf/uRLNode", uRLNode.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT );
}
if (zk .exists("/jfconf/userNameNode" , true)
== null) {
zk.create( "/jfconf/userNameNode", userNameNode .getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode. PERSISTENT);
}
if (zk .exists("/jfconf/passwdNode" , true)
== null) {
zk.create( "/jfconf/passwdNode", passwdNode.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT );
}
zk.close();
} catch (Exception e )
{
e.printStackTrace();
}
}
}
package example;
import java.io.IOException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
/**
* <p>
* 创建属于自己的Watcher,该Watcher监控 zk上的/jfconf 节点,
当该节点下的文件发生变化重新加载缓存
* </p>
*
* <p>
* ZooKeeper通过 Auth和ACL完成节点的权限控制
* </p>
*
* <p>
* Auth表示某种认证,由于一个ZooKeeper集群可能被多个项目使用,各个项目属于不同的项目组,
* 他们在进行开发时肯定不想其他项目访问与自己相关的节点,这时可以通过为每个项目组分配一个 Auth,
* 然后每个项目组先通过 Auth认证以后再继续相关的操作,这样甲 Auth认证的用户就不能操作其他
* Auth认证后创建的节点,从而实现各个项目之间的隔离。ZooKeeper提供了如下方法完成认证
* </p>
*
*
* @author shenfl
*
*/
public class MyClient implements Watcher
{
// zk的连接串
private final static String CONNECT_STR = "192.168.2.35:2181" ;
// 连接zk的超时时间
private static final int SESSION_TIMEOUT =
30000;
// client获取的数据库信息
private String uRL;
private String userName;
private String passwd;
// Auth认证
public static String authType = "digest" ;
public static String authPasswd = "*ik1234" ;
public MyClient()
{
initValue();
}
public static void main(String[] args)
{
MyClient client = new MyClient();
int i =
0;
try {
ZooKeeper zk = null;
// 连接zk
zk = new ZooKeeper(CONNECT_STR, SESSION_TIMEOUT , client );
// 判断权限是否能访问/ jfconf目录
zk.addAuthInfo( authType,authPasswd .getBytes());
while (true )
{
System. out.println("url[" + i + "]=" + client.getuRL());
System. out.println("userName[" + i + "]=" + client .getUserName());
System. out.println("passwd[" + i + "]=" + client .getPasswd());
Thread. sleep(10 * 1000);
i++;
if (i ==
10) {
break;
}
}
zk.close();
} catch (Exception e )
{
e.printStackTrace();
}
}
/**
* 获取 zk中相关信息
*
* @throws Exception
*/
private void initValue()
{
try {
ZooKeeper zk =
getZk();
/**
* return true: znode happened changed,uRL update.
*/
this.uRL = new String(zk.getData("/jfconf/uRLNode" , true, null));
this.userName = new String(zk.getData("/jfconf/userNameNode" , true, null));
this.passwd = new String(zk.getData("/jfconf/passwdNode" , true, null));
} catch (Exception e )
{
e.printStackTrace();
}
}
/**
* 获取 zk连接
*
* @return
* @throws IOException
*/
public ZooKeeper
getZk() {
ZooKeeper zk = null;
try {
zk = new ZooKeeper(CONNECT_STR, SESSION_TIMEOUT , this);
} catch (IOException e )
{
e.printStackTrace();
}
// 判断权限是否能访问/ jfconf目录
zk.addAuthInfo( authType,authPasswd .getBytes());
return zk ;
}
/**
* <p>
* 如何服务器中的配置信息发生变化,通知process方法,把 zk中的数据重新获取,然后放到缓存中
* </p>
*/
@Override
public void process(WatchedEvent event )
{
String message = "";
EventType type = event.getType();
if (type .equals(Watcher.Event.EventType.None))
{
message = "connect
zk sucess!!!";
} else if (type.equals(Watcher.Event.EventType.NodeCreated))
{
message = "znode
create sucess!!!";
} else if (type.equals(Watcher.Event.EventType.NodeChildrenChanged))
{
message = "child
of znode create sucess!!!";
} else if (type.equals(Watcher.Event.EventType.NodeDataChanged))
{
message = "znode
update success!!!,reload db's information";
initValue();
} else if (type.equals(Watcher.Event.EventType.NodeDeleted))
{
message = "znode
delete success!!!";
}
System. out.println(message );
}
public String
getuRL() {
return uRL ;
}
public void setuRL(String uRL )
{
this.uRL = uRL ;
}
public String
getUserName() {
return userName ;
}
public void setUserName(String userName )
{
this.userName = userName ;
}
public String
getPasswd() {
return passwd ;
}
public void setPasswd(String passwd )
{
this.passwd = passwd ;
}
}
3.3 验证Watcher
通过run as 运行MyClient.java,并查看结果
connect zk sucess!!!
url[0]=10.12.1.1
userName[0]=admin
passwd[0]=admin123
url[1]=10.12.1.1
userName[1]=admin
passwd[1]=admin123
url[2]=10.12.1.1
userName[2]=admin
passwd[2]=admin123
connect zk sucess!!!
url[3]=10.12.1.1
userName[3]=admin
passwd[3]=admin123
connect zk sucess!!!
然后修改/jfconf/userNameNode下的数据,再次检查结果
znode update success!!!,reload db's information
url[4]=10.12.1.1
userName[4]=adminadmin
passwd[4]=admin123
url[5]=10.12.1.1
userName[5]=adminadmin
passwd[5]=admin123
url[6]=10.12.1.1
userName[6]=adminadmin
passwd[6]=admin123
url[7]=10.12.1.1
userName[7]=adminadmin
passwd[7]=admin123
url[8]=10.12.1.1
userName[8]=adminadmin
passwd[8]=admin123
url[9]=10.12.1.1
userName[9]=adminadmin
passwd[9]=admin123
总结: 创建一个Watcher,然后注册到zk上,通过下面的代码完成注册
zk = new ZooKeeper( CONNECT_STR , SESSION_TIMEOUT, client);
ZooKeeper配置管理实战
本文介绍使用ZooKeeper进行配置管理的方法,包括配置信息的存储、变更通知及客户端自动同步更新等关键环节。
1万+

被折叠的 条评论
为什么被折叠?



