100303- ZooKeeper 配置管理代码实现案例

一、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 );


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾文教编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值