Chinaunix首页 | 论坛 | 博客
  • 博客访问: 584577
  • 博文数量: 104
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1559
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-21 00:58
个人简介

锻炼精神,首先要锻炼肉体

文章分类

全部博文(104)

文章存档

2018年(1)

2016年(1)

2015年(101)

2014年(1)

我的朋友

分类: Java

2015-07-27 18:08:32

在这篇博客中简单介绍一下,如何快速的在 linux 操作系统上搭建使用 zookeeper 客户端 curator 编程的单机环境。

在前几篇博客中,介绍的是使用 zookeeper 原生提供的 API 来编程的方法,其实,在 curator 出来之后,
使用 zookeeper 原生态 API 编程的方法就被很多人抛弃不用了。

在前面的文章中也简单的介绍了在一个 linux 主机上,通过配置多端口来部署一个"伪分布式" zookeeper 集群系统,
对于编写客户端的代码而言,单节点和"伪分布式" 两者并没有太大的区别。

在这里之所以使用单节点部署 zookeeper 服务器端的原因是最新稳定版本的 zookeeper 也就是 3.4.6 版本中,
有一个安全性的检查,如果配置不慎,很有可能触发安全性检测的日志打印,而这个安全性的检查将它的日志写到的异常中,
这就会出现,当 zookeeper 服务器进程启动之后,使用 zkCli.sh 启动客户端连接服务器端,会无休止的在控制台中
打印出异常信息,仔细看信息的话,就会发现全部是 WARN 级别的信息,但是却无法让使用者在命令端输入任何命令。

所以,出于这种原因,在这里介绍一下单点部署 zookeeper 的编程开发环境。

1. 将 zookeeper 安装包下载到路径 /usr/local 下,并解压压缩文件包
   并将 zookeeper-3.*.* 修改成为 zookeeper (为了配置文件书写起来方便一些)

2. 复制 ../conf/路径下面的配置文件模板 zoo_sample.cfg ,将其命名为 zoo.cfg ,
   修改 ../conf/路径下面的 zoo.cfg ,如下所示,
   注意 dataDir 路径的设置是 "/usr/local/zookeeper/data" ,那么在系统的对应路径下面要创建一个 data 文件夹
    
3. 修改了配置文件之后,接下来我们开始修改系统环境文件,在/etc/profile 文件结尾追加如下内容
  

   
4. 接着启动 zookeeper 服务器端 / zkServer.sh
   将路径切换到 zoo.cfg 所在的路径下面, 由于 zookeeper 的bin 路径已经被添加到系统 PATH 中,
   所以 zkServer.sh 会被系统自动的定位到 /usr/local/zookeeper/bin/ 的下面的。 
    
    [命令]  ./zkServer.sh start ./zoo.cfg 
    [命令|检测 zk server 是否运行] ps -aux | grep "zookeeper"
    [输出]   
    

5. 接着启动 zookeeper 的客户端 / zkCli.sh
   [命令] ./zkCli.sh 
    [输出]
   

6. 接着启动 linu 上的 IDE , 创建一个 maven module 项目 
    6.1 修改 pom.xml 在其中添加 curator(zookeeper 客户端) 的依赖
    

点击(此处)折叠或打开

  1. <dependencies>
  2.         <dependency>
  3.             <groupId>org.apache.curator</groupId>
  4.             <artifactId>curator-framework</artifactId>
  5.             <version>2.7.0</version>
  6.         </dependency>
  7.         <dependency>
  8.             <groupId>org.apache.curator</groupId>
  9.             <artifactId>curator-recipes</artifactId>
  10.             <version>2.7.0</version>
  11.         </dependency>
  12.         <dependency>
  13.             <groupId>org.apache.curator</groupId>
  14.             <artifactId>curator-test</artifactId>
  15.             <version>2.7.0</version>
  16.         </dependency>

  17.         <dependency>
  18.             <groupId>org.apache.zookeeper</groupId>
  19.             <artifactId>zookeeper</artifactId>
  20.             <version>3.4.6</version>
  21.         </dependency>


  22.     </dependencies>
   6.2 编写代码, 如下所示
 

点击(此处)折叠或打开

  1. package org.kylin;

  2. /**
  3.  * Created with IntelliJ IDEA.
  4.  * User: root
  5.  * Date: 7/24/15
  6.  * Time: 11:02 PM
  7.  * To change this template use File | Settings | File Templates.
  8.  */

  9. import org.apache.curator.utils.CloseableUtils ;
  10. import org.apache.curator.framework.CuratorFramework ;
  11. import org.apache.curator.framework.CuratorFrameworkFactory ;
  12. import org.apache.curator.framework.recipes.cache.ChildData ;
  13. import org.apache.curator.framework.recipes.cache.PathChildrenCache ;
  14. import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent ;
  15. import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener ;
  16. import org.apache.curator.retry.ExponentialBackoffRetry;
  17. import org.apache.curator.utils.ZKPaths ;

  18. public class SubPathChangeInvoker
  19. {
  20.     private static final String main_path = "/MainPath" ;

  21.     public static void main ( String args [] ) throws Exception
  22.     {
  23.         CuratorFramework client = null ;
  24.         PathChildrenCache cache = null ;

  25.         try
  26.         {
  27.             client = CuratorFrameworkFactory.builder()
  28.                             .connectString("127.0.0.1:2181")
  29.                             .sessionTimeoutMs(3000)
  30.                             .connectionTimeoutMs(3000)
  31.                             .canBeReadOnly(false)
  32.                             .retryPolicy( new ExponentialBackoffRetry(1000 , Integer.MAX_VALUE))

  33.                             .defaultData("aimer".getBytes())
  34.                             .build() ;
  35.             client.start() ;

  36.             System.out.println(" client running ") ;

  37.             // first we create the main path
  38.             client.create().forPath(main_path) ;


  39.             cache = new PathChildrenCache( client , main_path , true ) ;
  40.             cache.start() ;

  41.             // we add the listener inside the cache
  42.             cache.getListenable().addListener( addListenerToPathChildrenCache() );

  43.             // the listener and the events already registered inside in the PathChildrenCache's instance
  44.             // we let the IDE program wait for a while , and during this period we do some create, update , delete
  45.             // by zkCli.sh
  46.             // see what happens in this IDE program 's output
  47.             Thread.sleep(6000);

  48.             System.out.println("here we gonna create two sub nodes") ;
  49.             client.create().forPath(main_path+"/node1" , "node1".getBytes()) ;
  50.             client.create().forPath(main_path+"/node2", "node2".getBytes()) ;


  51.             System.out.println("delete the two sub nodes , we just create ") ;
  52.             client.delete().forPath(main_path+"/node1") ;
  53.             client.delete().forPath(main_path+"/node2") ;


  54.             System.out.println("here we gonna a loop for a very long time , do something on zkCli !") ;

  55.          while( true ) ;


  56.         }
  57.         finally
  58.         {
  59.              // close and relase resources in order
  60.               CloseableUtils.closeQuietly(cache); ;
  61.               CloseableUtils.closeQuietly(client);

  62.         }

  63.     }

  64.     private static PathChildrenCacheListener addListenerToPathChildrenCache ( )
  65.     {
  66.         // in this method , we first create an interface object which contain events
  67.         // invoke to different evnets , and then pass the interface : PathChildrenCacheListener
  68.         // into the cache this class instance

  69.         // if you refer to the api of the PathChildrenCacheListener , you will find there is one method
  70.         // with the name of childEvent declared in it , given / write the method for this method
  71.         // when the passed in cache finds out something happend to it the corresponding method will be called
  72.         // by different kinds of events {child add , child node remove , child node's data updated }


  73.         PathChildrenCacheListener listener = new PathChildrenCacheListener() {
  74.             @Override
  75.             public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent childEvent)
  76.                     throws Exception
  77.             {

  78.                 System.out.println("i am in childEvent ") ;

  79.                  switch (childEvent.getType() )
  80.                  {
  81.                      case CHILD_ADDED:
  82.                      {
  83.                          System.out.println("Node added : " + ZKPaths.getNodeFromPath(childEvent.getData().getPath() )) ;
  84.                          System.out.println("Node data is : "+ new String (childEvent.getData().getData() ) ) ;


  85.                          Thread.sleep(1000);
  86.                          break ;
  87.                      }
  88.                      case CHILD_UPDATED:
  89.                      {
  90.                          System.out.println("Node updated : " +ZKPaths.getNodeFromPath(childEvent.getData().getPath() )) ;
  91.                          System.out.println("Node data is (new ): " + new String (childEvent.getData().getData())) ;


  92.                          break ;
  93.                      }
  94.                      case CHILD_REMOVED:
  95.                      {
  96.                          System.out.println("Node removed : " +ZKPaths.getNodeFromPath(childEvent.getData().getPath())) ;
  97.                          break ;
  98.                      }
  99.                  }

  100.             }
  101.         } ; // new an instance of interface , remember add ";" at the end

  102.         // we have created a listener , now we add the listener into the cache object
  103.       return listener ;

  104.     }
  105. }

   6.3 在 zookeeper 客户端命令行中, 进行创建指定目录下面的子节点,删除子节点,更新子节点上的数据
    在 zkCli 控制台中输入命令
     
    
   6.4 查看 IDE 环境中的输出结果
 

手动退出,毕竟设定的是 while 死循环,后续的博客中会简单介绍使用 netty + zk 进行多各节点的网络编程/如果编译顺利的话.


end
阅读(1769) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

夏目玲子2015-07-27 18:11:54

对于 listener 中的触发事件,个人理解是这样的, 事件的触发和执行与主线程是异步执行的,
所以,你就看到了在 addListener 方法中的输出信息和主线程 main 方法中的输出数据二者交叉着显示在控制台中这种情况