ZooKeeper安装、使用的完整教程,SpringBoot整合ZooKeeper

zookeeper是为分布式应用程序提供的高性能协调服务。

文章来源地址https://uudwc.com/A/woypz

zookeeper将命名、配置管理、同步和组服务等常用服务公开在一个简单的接口中,因此用户无需从头开始编写这些服务。

可以使用它来实现共识、组管理、领导者选举和存在协议。还可以在此基础上满足自己的特定需求。开始学习zookeeper:zookeeper官网

zookeeper和nacos、eureka、consul都是我们常见的微服务注册中心,这篇文章就详细地介绍一下怎么安装zookeeper和使用zookeeper的客户端,以及通过springboot整合zookeeper。

zookeeper的数据结构

zookeeper的结构类似于文件系统,其中每一个目录叫做zookeeper的节点(znode),znode有以下几种类型:

  • 持久化节点:节点不会被自动删除,会一直存在。
  • 临时节点:一次会话结束后,临时节点会被删除。在创建节点的时候通过参数-e指定为临时节点。
  • 顺序节点:一般情况下,节点名已经存在,是无法创建同名节点的,但是顺序节点允许同名,创建的同名节点会被按顺序编号。在创建节点的时候通过参数-s指定为顺序节点。
  • 容器节点:容器节点是一种特殊的znode,当他下面的所有子节点都被删除时,该节点会被删除,每60秒会删除一次空的容器节点。在创建节点的时候通过参数-c指定为顺序节点。

 一、windows上安装zookeeper

首先,需要下载zookeeper,点击链接打开zookeeper官网Apache ZooKeeper,在官网首页点击Getting Started下面的Download进入下载页面

 选择下载稳定的版本

 下载完成后,解压到D盘,然后打开刚刚解压的zookeeper安装目录下的config目录,复制一份zoo_sample.cfg,然后重命名为zoo.cfg,修改里面的内容,dataLogDir是新增的,原来文件里没有

dataDir:zookeeper的安装目录\\data

dataLogDir:zookeeper的安装目录\\log

tickTime=2000

initLimit=10

syncLimit=5

clientPort=2181

dataDir=D:\\program\\apache-zookeeper-3.7.1\\data

dataLogDir=D:\\program\\apache-zookeeper-3.7.1\\log

然后在安装目录下新建两个目录data和log

经过以上的步骤,zookeeper就算安装完了。

启动zookeeper:双击zookeeper安装目录下的bin目录下的zkServer.bat

使用zookeeper:使用zookeeper的客户端,只需要双击zkCli.bat即可

 二、linux上安装zookeeper

上传压缩文件

文章使用linux版本为Ubuntu-22.04.3,通过finalshell上传刚刚下载的压缩包到服务器,并解压。

比如上传到/usr目录下,通过以下命令解压

tar -zvxf apache-zookeeper-3.7.1-bin.tar.gz

修改配置文件

修改一下zookeeper的文件夹名称为zookeeper-3.7.1,进入zookeeper安装目录下的conf目录,复制一份zoo_example.cfg,建议文件名为zoo.cfg,因为启动zk服务器的时候默认通过zoo.cfg配置文件启动,不需要指定配置文件名。

cd zookeeper-3.7.1/conf

cp zoo_sample.cfg zoo.cfg

然后修改zoo.cfg的dataDir

dataDir=/usr/local/zookeeper

三、启动zookeeper

通过以下命令启动zookeeper服务器

 bin/zkServer.sh start

如果配置文件名不是zoo.cfg,需要指定配置文件名

 bin/zkServer.sh start 配置文件名.cfg

四、使用zookeeper客户端

要使用zk客户端的命令之前,需要通过以下命令启动zookeeper的客户端

bin/zkCli.sh

然后通过help命令查看zookeeper有哪些命令

创建节点

可以通过zk客户端提供的的create命令创建znode。

create /test

 可以看到这个命令后面可以带很多个参数,当不带任何参数时,该节点默认为持久化节点。

接下来介绍这些参数的作用:

命令参数 作用
-s 指定节点类型为顺序节点
-e 指定节点类型为临时节点
-c 指定节点类型为容器节点
-t 指定节点的过期时间

临时节点

演示创建临时节点效果,依次在终端输入以下命令

./bin/zkCli.sh

create -e /test

get /test

quit

然后重新连接客户端

./bin/zkCli.sh

get /test

这时候通过get命令获取节点的数据,提示节点test不存在,是因为临时节点只在本次会话中有效,主动断开连接之后临时节点会被删除。

设置节点数据

set [-s] [-v version] /node_name data

-s修改该节点,并查看节点的状态,相当于以下两个命令的组合

set /test abc

get -s /test

 

-v指定版本号,只有当前数据的版本号和指定版本一样才会修改成功

比如接着上面的命令,再修改一次/test,让它的版本号dataVersion变成2,然后再次修改时通过-v指定版本号为1,此时会提示该版本号不存在,版本号机制是CAS操作中为了避免ABA问题而设置的。

获取节点数据

get [-s] [-w] /node_name

参数说明:

可选参数-s表示查看节点状态信息;

可选参数-w表示给节点添加一个监听器,这个监听器只会生效一次。

事件监听器

通过命令中指定的参数-w可以为创建/指定的节点添加一个监听器,监听节点的增删改操作,监听一次后将会移除该监听器。

通过addWatch命令可以给节点添加一个永久的监听器

 addWatch [-m mode] /node_name

mode表示监听的模式,有两种取值:

PERSISTENT:监听该节点的变化

PERSISTENT_RECURSIVE:监听该节点和其子节点的变化

 删除节点

delete:可以指定版本号删除

delete -v version /node_name

deleteall:递归删除当前节点和它的所有子节点

deleteall /node_name

五、springboot整合zookeeper

1、在IntelliJ IDEA里新建一个springboot项目,命名为zookeeper

2、在项目的pom.xml文件中引入zookeeper和相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.9</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>zookeeper</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>

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

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>5.2.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>5.2.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

3、修改application.xml配置文件,只需要指定项目启动端口号和zookeeper的服务器地址

server:
  port: 8085

zookeeper:
  host: localhost:2181

4、项目根目录下创建config包,新建一个zookeeper的配置类

package com.example.zookeeper.config;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author heyunlin
 * @version 1.0
 */
@Configuration
public class ZookeeperConfig {

    @Value("${zookeeper.host}")
    private String host;

    @Bean
    public CuratorFramework curatorFramework() {
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
                .connectString(host)
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(500, 5))
                .build();
        curatorFramework.start();

        return curatorFramework;
    }

}

5、使用zookeeper的API

package com.example.zookeeper.controller;

import com.example.zookeeper.restful.JsonResult;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author heyunlin
 * @version 1.0
 */
@RestController
@RequestMapping(path = "/zookeeper", produces = "application/json;charset=utf-8")
public class ZookeeperController {
    private final CuratorFramework curatorFramework;

    @Autowired
    public ZookeeperController(CuratorFramework curatorFramework) {
        this.curatorFramework = curatorFramework;
    }

    /**
     * 判断znode是否存在
     * @param node 节点名称
     */
    @RequestMapping(value = "/exist", method = RequestMethod.GET)
    public JsonResult<Stat> exist(String node) throws Exception {
        Stat stat = curatorFramework.checkExists().forPath(node);

        return JsonResult.success(null, stat);
    }

    /**
     * 创建一个znode
     * @param node 节点名称
     */
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public JsonResult<Void> create(String node) throws Exception {
        curatorFramework.create()
                .creatingParentContainersIfNeeded()
                /*
                创建模式:常用的有
                    PERSISTENT:持久化节点,客户端与zookeeper断开连接后,该节点依旧存在,只要不手动删除,该节点就会永远存在。
                    PERSISTENT_SEQUENTIAL:持久化顺序编号目录节点,客户端与zookeeper断开连接后,该节点依旧存在,只是zookeeper给该节点名称进行顺序编号。
                    EPHEMERAL:临时目录节点,客户端与zookeeper断开连接后,该节点被删除。
                    EPHEMERAL_SEQUENTIAL:临时顺序编号目录节点,客户端与zookeeper断开连接后,该节点被删除,只是zookeeper给该节点名称进行顺序编号。
                */
                .withMode(CreateMode.EPHEMERAL)
                .forPath(node);

        return JsonResult.success("创建成功");
    }

    /**
     * 设置znode节点的数据
     * @param node 节点名称
     * @param data 节点的数据
     */
    @RequestMapping(value = "/setData", method = RequestMethod.GET)
    public JsonResult<Void> setData(String node, String data) throws Exception {
        curatorFramework.setData().forPath(node, data.getBytes(StandardCharsets.UTF_8));

        return JsonResult.success("设置成功");
    }

    /**
     * 删除节点
     * @param node 节点名称
     */
    @RequestMapping(value = "/delete", method = RequestMethod.GET)
    public JsonResult<Void> delete(String node) throws Exception {
        curatorFramework.delete().forPath(node);

        return JsonResult.success("删除成功");
    }

    /**
     * 删除节点及其子节点的数据
     * @param node 节点名称
     */
    @RequestMapping(value = "/deleteDeeply", method = RequestMethod.GET)
    public JsonResult<Void> deleteDeeply(String node) throws Exception {
        curatorFramework.delete().deletingChildrenIfNeeded().forPath(node);

        return JsonResult.success("删除成功");
    }

    /**
     * 获取节点的数据
     * @param node 节点名称
     */
    @RequestMapping(value = "/getData", method = RequestMethod.GET)
    public JsonResult<String> getData(String node) throws Exception {
        byte[] bytes = curatorFramework.getData().forPath(node);

        return JsonResult.success(null, new String(bytes));
    }

    /**
     * 获取当前节点的子节点数据
     * @param node 节点名称
     */
    @RequestMapping(value = "/getChildren", method = RequestMethod.GET)
    public JsonResult<List<String>> getChildren(String node) throws Exception {
        List<String> list = curatorFramework.getChildren().forPath(node);

        return JsonResult.success(null, list);
    }

}

好了,文章就分享到这里了~

原文地址:https://blog.csdn.net/heyl163_/article/details/131693756

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年09月25日 12:31
科技资讯|Canalys发布全球可穿戴腕带设备报告,智能可穿戴增长将持续
下一篇 2023年09月25日 12:39