一、简介

  ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

二、环境

  Windows或者Centos7,本例中使用Centos7测试,Windows上的用和Linux是相似的,只是启动解本执行对应.bat而不是.sh即可。

三、部署

  1、下载最新版(3.4.13):https://archive.apache.org/dist/zookeeper/  下载https://archive.apache.org/dist/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz解压开即可。

  2、解压开后,进入conf目录:

    (a)如果是要配置单节点,则然后复制并重命名zoo_sample.cfg文件为zoo.cfg,然后修改zoo.cfg如下:

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=D:\\Applicaton\\DevTools\\Zookeeper\\zookeeper-3.4.13\\data
dataLogDir=D:\\Applicaton\\DevTools\\Zookeeper\\zookeeper-3.4.13\\log
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

    配置说明:

tickTime:zookeeper中使用的基本时间单位, 毫秒值。 
initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个 tickTime 时间间隔数。这里设置为5表名最长容忍时间为 5 * 2000 = 10 秒。 
syncLimit:这个配置标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2 * 2000 = 4 秒。 
dataDir 和 dataLogDir 看配置就知道干吗的了,不用解释,Windows上和Linux上都可以,配置相应目录即可,使用\\来作\的转义。 
clientPort:监听client连接的端口号,这里说的client就是连接到Zookeeper的代码程序。 
server.{myid}={ip}:{leader服务器交换信息的端口}:{当leader服务器挂了后, 选举leader的端口} 
maxClientCnxns:对于一个客户端的连接数限制,默认是60,这在大部分时候是足够了。但是在我们实际使用中发现,在测试环境经常超过这个数,经过调查发现有的团队将几十个应用全部部署到一台机器上,以方便测试,于是这个数字就超过了。

    (b)如果是要配置多节点,则复制并重命名zoo_sample.cfg为zoo.server1.cfg、zoo.server2.cfg、zoo.server3.cfg三个文件,并追加server.<myid>=<serverIP>:<Leader交换信息端口>:<当Leader挂了后选举Leader的端口>。

server.{myid}={ip}:{leader服务器交换信息的端口}:{当leader服务器挂了后, 选举leader的端口} 

  其中zoo.server1.cfg内容如下:

# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/tmp/zookeeper/server1
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1i
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890

  其中zoo.server2.cfg内容如下:

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/tmp/zookeeper/server2
# the port at which the clients will connect
clientPort=2182

# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1i
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890

  其中zoo.server3.cfg内容如下:

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/tmp/zookeeper/server3
# the port at which the clients will connect
clientPort=2183
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1i
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890

  3、创建数据目录:

  如果前面的配置是使用多节点集群模式时,请在相应的数据dataDir参数的目录下面创建一个名为myid的文件,内容就写各个服务器的myid标记,例如:前面的多节点配置中,在/tmp/zookeeper/server1、/tmp/zookeeper/server2、/tmp/zookeeper/server3目录下分别创建一个名为myid的文件,内容分别是:1、2、3。

  可用下列角本快速创建实现:

echo 1>/tmp/zookeeper/server1/myid
echo 2>/tmp/zookeeper/server2/myid
echo 3>/tmp/zookeeper/server3/myid

  如果不配置此步,则会出现下列错误:Caused by: java.lang.IllegalArgumentException: /tmp/zookeeper/server3/myid file is missing

 

  3、启动程序

  (a)如果是单节点程序,则进入zookeeper解压目录下执行:./bin/zkServer.sh start即可,系统默认会查找./conf/zoo.cfg作为配置文件。在Windows上则直接执行/bin/zkServer.bat即可。

  (b)如果是多节点程序,则进入zookeeper解压目录下分别执行:

./bin/zkServer.sh start ./conf/zoo.server1.cfg
./bin/zkServer.sh start ./conf/zoo.server2.cfg
./bin/zkServer.sh start ./conf/zoo.server3.cfg

   (c)使用ss -tanl或者netstat -lpen命令检查服务是否已启动。

 

 三、用法

  Zookeeper提供了Java操作的API,用法网上一找一大堆,本文就讲讲C#使用Zookeeper.net库操作的方法。

  (1)新建Netframework控制台项目,并Nuget引入下列包:https://www.nuget.org/packages/ZooKeeper.Net/

  (2)日志配置:

    (a)在项目中新建log4net.config文件,并设置输出方式为:【如果较新则复制】 内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<configuration status="ON">
  <log4net>
    <!--<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout" value="%date [%thread] %-5level %logger - %message%newline" />
    </appender>-->
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="logs/" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <staticLogFileName value="false" />
      <datePattern value="yyyyMMdd'.log'" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="1MB" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>
    <root level="WARN">
      <!--<appender-ref ref="ConsoleAppender" />-->
      <appender-ref ref="RollingLogFileAppender" />
    </root>
  </log4net>
</configuration>

  (3)新建类:MyWatcher,内容如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZooKeeperNet;

namespace ZookeeperDemo
{
    class MyWatcher : ZooKeeperNet.IWatcher
    {
        public void Process(WatchedEvent @event)
        {
            var old = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(">>>>> Path:" + @event.Path + "   State:" + @event.State + "   Type:" + @event.Type);
            Console.ForegroundColor = old;
        }
    }
}

  (4)在Program类中,注意连接集群时,用","分隔主机与Port。这样写:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ZooKeeperNet;

namespace ZookeeperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //配置日志
            log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo("log4net.config"));
            //测试Zookeper
            using (ZooKeeperNet.ZooKeeper zk = new ZooKeeperNet.ZooKeeper("xxx.xxx.xxx.xxx:2181,xxx.xxx.xxx.xxx:2182,xxx.xxx.xxx.xxx:2183", TimeSpan.FromSeconds(50), new MyWatcher()))
            {
                //注意,当第一次调用命令时,Zookeeper可能还未连接到服务器。此时是调用命令会提示ZooKeeperNet.KeeperException.ConnectionLossException错误,所以要当收到服务器第1次返回SyncConnected给MyWatcher时,再开始往下执行代码,或者判断State再往下走。
                while (zk.State != ZooKeeper.States.CONNECTED)
                {
                    Thread.Sleep(100);
                    Console.WriteLine("Connect ...");
                }
                Org.Apache.Zookeeper.Data.Stat stat = zk.Exists("/root", true);//使用 exists 函数时,如果节点不存在将返回一个 null 值。
                if (stat != null)
                {
                    //删除前,要先删除子节点。
                    var nodes = zk.GetChildren("/root", false);
                    foreach (var item in nodes)
                    {
                        zk.Delete(string.Format("/root/{0}", item), -1);
                    }
                    zk.Delete("/root", -1);//前一个参数代表节点名称(一般用作路径),后一个是版本号 -1表示全匹配
                }

                Console.WriteLine("Begin Create Node");
                String createResult = zk.Create("/root", "Song".GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);//在创建节点的时候,需要提供节点的名称、数据、权限以及节点类型。
                Console.WriteLine("Create Node Success:" + createResult);//return '/root'


                Console.WriteLine("Begin Get Data");
                var bys = zk.GetData("/root", true, null);
                Console.WriteLine("Get Data Success:" + Encoding.UTF8.GetString(bys));//return 'Song' 

                Console.WriteLine("Begin Update Data");
                var statSet = zk.SetData("/root", "Sindrol".GetBytes(), -1);//数据量应为1MB以下。
                if (statSet != null) Console.WriteLine("Update data Success!");

                Console.WriteLine("Create data Sequential.");
                zk.Create("/root/", "data1".GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PersistentSequential); //路径中使用/结尾,则创建节点时当CreateMode.*Sequential时,会以数字序列形式生成子节点。
                zk.Create("/root/", "data2".GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PersistentSequential);

                Console.WriteLine("Get Children:");
                IEnumerable<string> lst = zk.GetChildren("/root", true).ToList().ConvertAll(s => "/root/" + s);
                if (lst != null) Console.WriteLine("Get Children Success:" + string.Join(",", lst));

                Console.WriteLine("Get Children Data:");
                foreach (var item in lst)
                {
                    var path = item;
                    var dataBys = zk.GetData(path, true, null);
                    Console.WriteLine(Encoding.UTF8.GetString(dataBys));
                }
            }
        }
    }
}

  好了,上面的代码就不多解释了,是最简单的了,和原生API也是很像的。

四、使用zkCli命令行工具

  1、在zookeeper安装包解压目录下执行下列命令连接到Zookeeper并进入命令行模式,输入quit退出。

./bin/zkCli.sh -server 127.0.0.1:2181
./bin/zkCli.sh -server 127.0.0.1:2182
./bin/zkCli.sh -server 127.0.0.1:2183

  2、命令行操作:

 

 五、说明

  Zookeeper集群操作时,当Set数据时,它会同时给所有的服务器设置相同的数据,保证数据一致性,内存中Zookeeper会维护一个Linux结构的树型目录。设置数据时,数量量最大是1MB,不要太多。

 

转载于:https://www.cnblogs.com/songxingzhu/p/9329647.html

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐