加载中...

快速部署单机 zookeeper 集群(win 环境)


1. 前言

本文不讲 zookeeper 集群原理,只谈部署步骤。

默认读者已对 zookeeper 有最基本的认知,纯粹作为部署笔记,方便回忆。

另外本文是基于 Windows 部署的,Linux 的步骤是基本相同的(只是启动脚本位置不同)。

严格来说本文部署的是单机伪集群,但一理通百理明,多主机集群和单机伪集群的部署方式相差无几,从入门角度看,使用方式也是大同小异。

2. 环境

  • JDK : 1.8
  • zookeeper : 3.4.7
  • zookeeper 集群规模 : 3
  • zookeeper 安装目录 :%INSTALL_DIR% = E:\apache\apache-zookeeper(此处定义变量是为了下文方便说明,实际部署时应使用实际路径而非变量

3. 安装

到 zookeeper 官网下载最新版:https://zookeeper.apache.org/

解压后,复制并重命名到 3 个目录(每个目录代表 zookeeper 集群的一台机器):

%INSTALL_DIR%/zookeeper-1
%INSTALL_DIR%/zookeeper-2
%INSTALL_DIR%/zookeeper-3

分别复制这三个目录下的配置文件:

%INSTALL_DIR%/zookeeper-x/conf/zoo_sample.cfg

并重命名为:

%INSTALL_DIR%/zookeeper-x/conf/zoo.cfg

4. 配置

修改配置文件 %INSTALL_DIR%/zookeeper-1/conf/zoo.cfg 的参数如下(注意实际部署时把变量 %INSTALL_DIR% 改成实际路径):

dataDir=%INSTALL_DIR%/zookeeper-1/data
dataLogDir=%INSTALL_DIR%/zookeeper-1/log
clientPort=2181
server.1=localhost:2287:3287
server.2=localhost:2288:3288
server.3=localhost:2289:3289

修改配置文件 %INSTALL_DIR%/zookeeper-2/conf/zoo.cfg 的参数如下(注意实际部署时把变量 %INSTALL_DIR% 改成实际路径):

dataDir=%INSTALL_DIR%/zookeeper-2/data
dataLogDir=%INSTALL_DIR%/zookeeper-2/log
clientPort=2182
server.1=localhost:2287:3287
server.2=localhost:2288:3288
server.3=localhost:2289:3289

修改配置文件 %INSTALL_DIR%/zookeeper-3/conf/zoo.cfg 的参数如下(注意实际部署时把变量 %INSTALL_DIR% 改成实际路径):

dataDir=%INSTALL_DIR%/zookeeper-3/data
dataLogDir=%INSTALL_DIR%/zookeeper-3/log
clientPort=2183
server.1=localhost:2287:3287
server.2=localhost:2288:3288
server.3=localhost:2289:3289

同时,分别在 3 个%INSTALL_DIR%/zookeeper-x/data 目录下,新建一个名为 myid 文件,其中:

%INSTALL_DIR%/zookeeper-1/data/myid 中的内容为1,对应server.1中的1
%INSTALL_DIR%/zookeeper-2/data/myid 中的内容为2,对应server.2中的2
%INSTALL_DIR%/zookeeper-3/data/myid 中的内容为3,对应server.3中的3

关于 zoo.cfg 配置文件的部分配置参数说明:

  • tickTime : zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,亦即每个 tickTime 时间就会发送一个心跳。
  • dataDir : zookeeper 保存数据的目录,默认情况下,zookeeper 将写数据的日志文件也保存在这个目录。
  • clientPort : 客户端连接 zookeeper 服务器的端口,zookeeper 会监听这个端口,接受客户端的访问请求。
  • initLimit : zookeeper 接受客户端(不是用户连接 zookeeper 服务器的客户端,而是 zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。
  • syncLimit : 标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度。
  • server.A=B:C:D ,其中:
      - A 是一个数字,表示这个是第几号服务器。
      - B 是这个服务器的 ip 地址。
      - C 是这个服务器与集群中的 Leader 服务器交换信息的端口。
      - D 是在执行选举时,服务器相互通信的端口:万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,就是用这个端口。
      - 如果是(如本文所述的)伪集群的配置方式,由于 B 都是一样,而不同的 zookeeper 实例通信端口号不能一样,此时要给 C、D 分配不同的端口号。

5. 运行

%INSTALL_DIR% 目录下新建一个 run-all-zk.bat 脚本,内容如下(注意实际部署时把变量 %INSTALL_DIR% 改成实际路径):

start %INSTALL_DIR%/zookeeper-1/bin/zkServer.cmd
start %INSTALL_DIR%/zookeeper-2/bin/zkServer.cmd
start %INSTALL_DIR%/zookeeper-3/bin/zkServer.cmd

这样只需运行 run-all-zk.bat 脚本,即可启动整个 zookeeper 集群。

至此 zookeeper 部署完成 。

6. 管理 zookeeper 节点

若要管理 zookeeper 节点,推荐使用工具:ZKInspector

启动后,输入连接字符串即可连接到 zookeeper: localhost:2181,localhost:2182,localhost:2183

此工具可以很方便地增删改查 zookeeper 当前的节点状态和内容。

7. 使用 Java 测试 zookeeper 集群

7.1. 官方样例

官方的 Maven 原生构件:

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.6</version>
</dependency>

官方测试代码:

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

/**
 * <PRE>
 * apache-zookeeper测试
 * </PRE>
 * <B>PROJECT : </B> zookeeper
 * <B>SUPPORT : </B> <a href="https://exp-blog.com" target="_blank">exp-blog.com</a> 
 * @version   2018-08-02
 * @author    EXP: 272629724@qq.com
 * @since     jdk版本:jdk1.6
 */
public class TestZooKeeper {

    public static void main(String[] args) throws Exception {
        new TestZooKeeper().test();
    }

    public void test() throws Exception {
        final String CHARSET = "UTF-8";

        /* 连接到zookeeper集群 */
        final String ZK_CONN_STR = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183";
        final int sessionTimeout = 300000;
        NodeWatcher nodeWatcher = new NodeWatcher(); // zookeeper节点监视器(当节点发生变化时, 会触发此监视器)
        ZooKeeper zk = new ZooKeeper(ZK_CONN_STR, sessionTimeout, nodeWatcher);

        /*
         * 阻塞等待连接到zookeeper集群.
         * 若zookeeper已经启动一段时间是不需要循环检测的,此方法目的是兼容zookeeper刚刚启动的情况.
         */
        while(!zk.getState().equals(ZooKeeper.States.CONNECTED)) {
            Thread.sleep(1000);
        }

        /* 若zookeeper节点不存在,则创建之 */
        String nodePath = "/zk-test-node";    // 节点位置
        Stat stat = zk.exists(nodePath, false);
        if(stat == null) {
            String nodeData = "http://exp-blog.com";    // 节点数据

            // 创建一个持久化节点(即在zookeeper服务停止后依然可以保存该节点数据)
            // 与之相对的则是 CreateMode.EPHEMERAL 临时节点(即在zookeeper服务停止后该节点数据丢失)
            zk.create(nodePath, nodeData.getBytes(CHARSET), 
                    ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }

        /* 从zookeeper节点上读取数据 */
        byte[] bytes = zk.getData(nodePath, false, stat);
        String nodeData = new String(bytes, CHARSET);
        System.out.println(nodeData);

        /* 断开zookeeper连接 */
        zk.close();
    }

    /**
     * <PRE>
     * zookeeper节点监视器(当节点发生变化时, 会触发此监视器)
     * </PRE>
     * <B>PROJECT : </B> zookeeper
     * <B>SUPPORT : </B> <a href="http://www.exp-blog.com" target="_blank">www.exp-blog.com</a> 
     * @version   2018-08-02
     * @author    EXP: 272629724@qq.com
     * @since     jdk版本:jdk1.6
     */
    private class NodeWatcher implements Watcher {

        @Override
        public void process(WatchedEvent event) {
            System.out.println("-----------");
            System.out.println("path:" + event.getPath());
            System.out.println("type:" + event.getType());
            System.out.println("stat:" + event.getState());
            System.out.println("-----------");
        }
    }
}

7.2. Github 样例(更精简的 zk 客户端)

zkclient 的 Maven 构件:

<dependency>
    <groupId>com.github.adyliu</groupId>
    <artifactId>zkclient</artifactId>
    <version>2.1.1</version>
</dependency>

zkclient 测试代码:

import com.github.zkclient.ZkClient;

/**
 * <PRE>
 * zkClient测试
 * </PRE>
 * <B>PROJECT : </B> zookeeper
 * <B>SUPPORT : </B> <a href="https://exp-blog.com" target="_blank">exp-blog.com</a> 
 * @version   2018-08-02
 * @author    EXP: 272629724@qq.com
 * @since     jdk版本:jdk1.6
 */
public class TestZooKeeperClient {

    public static void main(String[] args) throws Exception {

        /* 连接到zookeeper集群 */
        final String ZK_CONN_STR = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183";
        ZkClient zkClient = new ZkClient(ZK_CONN_STR);

        /* 若zookeeper节点不存在,则创建之 */
        String nodePath = "/zk-test-node";    // 节点位置
        if (!zkClient.exists(nodePath)) {
            String nodeData = "http://exp-blog.com";    // 节点数据

            // 创建一个持久化节点(即在zookeeper服务停止后依然可以保存该节点数据)
            // 与之相对的则是 createEphemeral 临时节点(即在zookeeper服务停止后该节点数据丢失)
            zkClient.createPersistent(nodePath, nodeData.getBytes());
        }

        /* 从zookeeper节点上读取数据 */
        String nodeData = new String(zkClient.readData(nodePath));
        System.out.println(nodeData);
    }

}

资源下载


文章作者: EXP
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 EXP !
  目录