Zookeeper-使用篇

一、Zookeeper操作-linux

节点的基本操作

①、创建节点(create)

创建ZK节点

  • 默认情况下,不添加-s或者-e参数的,创建的是持久节点。
# 格式:【参数:-s:顺序节点;-e:临时节点】
create [-s] [-e] path data acl

# 实例
create /zk-book java

②、读取节点 (ls & get)

读取节点信息ls命令和set命令。

# 格式
ls path [watch]

# 实例
ls /

使用get命令,可以获取zookeeper指定节点的数据内容和属性信息。

# 格式
get path [watch]

# 实例
get /zk-book

③、更新节点(set)

使用set命令,可以更新指定节点的数据内容。

# 格式
set path data [version]

# 实例
set /zk-book springcloud
  • 参数:
  1. data就是要更新的新内容。
  2. 注意,set命令后面还有一个version参数,在ZooKeeper 中,节点的数据是有版本概念的,这个参数用于指定本次更新操作是基于ZNode的哪一个数据版本进行的。

④、删除节点(delete)

删除zookeeper上的指定节点。

# 格式
delete path [version]

# 实例
delete /zk-book

⑤、节点的状态结构(stat)

每个节点都有属于自己的状态信息,这就很像每个人的身份信息一样。

# 格式
stat path

# 实例
stat /a
  • 状态
状态属性 说明
czxid 表示该数据节点被创建时的事务 ID
mzxid 表示该数据节点最后一次被更新时的事务 ID
pzxid 表示该数据节点的子节点列表最后一次被更新时的事务 ID
ctime 表示该节点的创建时间
mtime 表示该节点最后一次被更新的时间
version 数据节点的版本号
cversion 子节点的版本号
aversion 节点的ACL版本号
ephemeralOwner 创建该临时节点的会话 SessionID 如果该节点是持久节点,那么这个属性值是 0
dataLength 数据内容的长度
numChildren 当前节点的子节点个数

节点的监听

zooKeeper 提供了分布式数据的发布/订阅功能。一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能够让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使它们能够做出相应的处理。

①、监听节点变化

# 格式
ls -w path

# 实例
ls -w /zk-book
  • 参数:
  1. 命令如果使用watch,那么监听的是节点的变化,而不是值的变化。

②、监听节点的值的变化

# 格式
get -w path

# 实例
get -w /zk-book
  • 参数:
  1. watch监听机制只能够使用一次,如果下次想要使用,必须重新监听,就比如ls path watch命令,只能监听节点路径的改变一次,如果还想监听,那么需要再执行一次ls path watch命令。

节点的权限控制

在ZooKeeper的实际使用中,我们的做法往往是搭建一个共用的ZooKeeper集群,统一为若干个应用提供服务。在这种情况下,不同的应用之间往往是不会存在共享数据的使用场景的,因此需要解决不同应用之间的权限问题。

  • ACL 权限控制
  1. 权限模式(Schema)
  2. 授权对象(ID)
  3. 权限(Permission)`

①、设置权限

# 格式
setAcl path schema:id:permission

# 实例
setAcl /test2 ip:128.0.0.1:crwda

schema

ZooKeeper内置了一些权限控制方案(schema),可以用以下方案为每个节点设置权限:

方案 描述
world 只有一个用户:anyone,代表所有人(默认)
ip 使用IP地址认证
auth 使用已添加认证的用户认证
digest 使用“用户名:密码”方式认证

id

授权对象ID是指,权限赋予的用户或者一个实体,例如:IP 地址或者机器。授权模式 schema 与 授权对象 ID 之间关系:

权限模式 授权对象
IP 通常是一个IP地址或是IP段,例如“192.168.66.101”
Digest 自定义,通常是“username:BASE64(SHA-1(username:password))”
World 只有一个ID:“anyone”
Super 与Digest模式一致

permission

权限 ACL简写 描述
CREATE c 可以创建子节点
DELETE d 可以删除子节点(仅下一级节点)
READ r 可以读取节点数据及显示子节点列表
WRITE w 可以设置节点数据
ADMIN a 可以设置节点访问控制列表权限

②、其他命令

命令 使用方式 描述
getAcl getAcl 读取ACL权限
setAcl setAcl 设置ACL权限
addauth addauth 添加认证用户

zookeeper高级

之前使用stat命令来验证ZooKeeper服务器是否启动成功,这里的stat命令就是ZooKeeper 中最为典型的命令之一。ZooKeeper中有很多类似的命令,它们的长度通常都是4个英文字母,因此我们称之为“四字命令”。

  • 添加配置
vim /usr/local/zookeeper/conf/zoo.cfg

4lw.commands.whitelist=*

conf

输出Zookeeper相关服务的详细配置信息,如客户端端口,数据存储路径、最大连接数、日志路径、数据同步端口、主节点推举端口、session超时时间等等。

echo conf| nc localhost 2181

cons

cons 命令用于输出当前这台服务器上所有客户端连接的详细信息,包括每个客户端的客户端IP、会话ID和最后一次与服务器交互的操作类型等。

echo cons | nc localhost 218

ruok

ruok命令用于输出当前ZooKeeper服务器是否正在运行。该命令的名字非常有趣,其谐音正好是“Are you ok”。执行该命令后,如果当前ZooKeeper服务器正在运行,那么返回“imok”, 否则没有任何响应输出。

echo ruok | nc localhost 2181

stat

stat命令用于获取ZooKeeper服务器的运行时状态信息,包括基本的ZooKeeper版本、打包信息、运行时角色、集群数据节点个数等信息,另外还会将当前服务器的客户端连接信息打印出来。

echo stat | nc localhost 2181

mntr

列出集群的关键性能数据,包括zk的版本、最大/平均/最小延迟数、数据包接收/发送量、连接数、zk角色(Leader/Follower)、node数量、watch数量、临时节点数。

echo mntr | nc localhost 2181

二、Zookeeper操作-JAVA

version1.0

导入依赖

zookeeper原生api

  1. 重复注册watcher
  2. session失效重连
  3. 异常处理(删除节点不能有子节点,新增节点必须有父节点等)
    <dependencies>
        <!-- zookeeper原生api -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.8</version>
        </dependency>
    </dependencies>

配置文件

获取zookeeper链接

    public static void main(String[] args) throws IOException {
    
    
        /**
         * 创建一个 Zookeeper 的实例
         * 此处为一个集群,Zookeeper 的 ip 之间用逗号隔开
         * 参数解释:
         * param 1 - Zookeeper 的实例 ip ,此处是一个集群,所以配置了多个 ip,用逗号隔开
         * param 2 - session 过期时间,单位秒(1000)
         * param 3 - 监视者,用于获取监听事件(MyWatch)
         */
        ZooKeeper zooKeeper = new ZooKeeper("ip:2181", 5000, null);
        // 1. 查看链接状态
        System.out.println(zooKeeper.getState());
    }

操作zookeeper

节点操作

①、创建节点
  • znode 类型有四种:
类型 含义
PERSISTENT 持久化目录节点,客户端与zookeeper断开连接后,该节点依旧存在
PERSISTENT_SEQUENTIAL 持久化,并带有序列号
EPHEMERAL 临时目录节点,客户端与zookeeper断开连接后,该节点被删除
EPHEMERAL_SEQUENTIAL 临时,并带有序列号
    /**
     * 创建节点
     */
    private static void createNodeSync(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
    
    
        String path = "/node1";
        /**
         * 参数一:znode名称
         * 参数二:节点数据
         * 参数三:设置权限
         * 参数四:znode类型
         */
        String nodePath = zooKeeper.create(path, "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println(nodePath);
    }
②、读取节点&结构状态
    /**
     * 读取数据信息
     * 1. 节点数据
     * 2. 节点数据状态信息
     */
    private static void getDataSync(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
    
    
        Stat stat = new Stat();
        /**
         * getData的返回值是该节点的数据值,节点的状态信息会赋值给stat对象
         * 参数一:节点名称
         * 参数二:监听机制(null不触发)
         * 参数三:状态信息
         */
        byte[] data = zooKeeper.getData("/node1", true, stat);
        System.out.println(new String(data));
        System.out.println(stat);
    }
③、更新节点数据
    /**
     * 更新节点数据
     */
    private static void setDataSync(ZooKeeper zooKeeper) throws InterruptedException, KeeperException {
    
    
        /**
         * 参数一:znode名称
         * 参数二:节点数据
         * 参数三:该节点的版本,(-1代表全部)
         */
        Stat stat = zooKeeper.setData("/node1", "java-zookeeper".getBytes(), -1);
        System.out.println(stat);
    }
④、删除节点
    /**
     * 删除节点
     */
    private static void deleteSync(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
    
    
        /**
         * 参数一:节点名称
         * 参数二:节点版本
         */
        zooKeeper.delete("/node1", -1);
    }
⑤、查看节点是否存在
    /**
     * 查看节点是否存在
     */
    private static void existSync(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
    
    
        /**
         * 参数一:节点名称
         * 参数二:监听机制
         */
        Stat stat = zooKeeper.exists("/node1", true);
        System.out.println(stat);
    }

节点的监听

①、监听节点

通过zkCli.getchildren(“/”,new watch()){}来注册监听,监听的是整个根节点,但是这个监听只能监听一次。线程休眠是为了让监听等待事件发生,不然会随着程序直接运行完。

    /**
     * 监听节点
     */
    private static void watcherNodeSync(ZooKeeper zooKeeper) throws InterruptedException, KeeperException {
    
    
        /**
         * 监听目录节点(只监听一次)
         * 参数一:监听路径
         * 参数二:回调函数
         */
        zooKeeper.getChildren("/", new Watcher() {
    
    
            public void process(WatchedEvent event) {
    
    
                System.out.println("监听路径为:" + event.getPath());
                System.out.println("监听的类型为:" + event.getType());
                System.out.println("数据被2货修改了!!!");
            }
        });
        Thread.sleep(Long.MAX_VALUE);
    }
②、监听数据

getData监听的为一个节点,同样只监听一次,返回的是该节点的内容。

    /**
     * 监听数据
     */
    private static void watcherDataSync(ZooKeeper zooKeeper) throws InterruptedException, KeeperException {
    
    
        /**
         * 监听目录节点(只监听一次)
         * 参数一:监听路径
         * 参数二:回调函数
         */
        byte[] data = zooKeeper.getData("/node1", new Watcher() {
    
    
            //监听的具体内容
            public void process(WatchedEvent event) {
    
    
                System.out.println("监听路径为:" + event.getPath());
                System.out.println("监听的类型为:" + event.getType());
                System.out.println("数据被2货修改了!!!");
            }
        }, null);
        System.out.println(new String(data));
        Thread.sleep(Long.MAX_VALUE);
    }

version2.0

zkclient是Github上一个开源的Zookeeper客户端,在Zookeeper原生 API接口之上进行了包装,是一个更加易用的Zookeeper客户端。同时Zkclient在内部实现了诸如Session超时重连,Watcher反复注册等功能,从而提高开发效率。

导入依赖

    <dependencies>
        <!-- zkclient -->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
    </dependencies>

配置文件

    public static void main(String[] args) {
    
    
        /**
         * 创建会话,多个地址用逗号隔开
         * 参数:zookeeper地址端口
         */
        ZkClient zk = new ZkClient("ip:2181");
        // 1. 查看连接状态
        System.out.println(zk.getShutdownTrigger());
    }

操作zookeeper

节点操作

  • znode 类型有四种:
类型 含义
PERSISTENT 持久化目录节点,客户端与zookeeper断开连接后,该节点依旧存在
PERSISTENT_SEQUENTIAL 持久化,并带有序列号
EPHEMERAL 临时目录节点,客户端与zookeeper断开连接后,该节点被删除
EPHEMERAL_SEQUENTIAL 临时,并带有序列号
①、创建节点
    /**
     * 创建节点
     */
    private static void createNodeSync(ZkClient zk) throws KeeperException, InterruptedException {
    
    
        /**
         * 参数一:节点名称
         * 参数二:节点数据
         * 参数三:
         */
        String res = zk.create("/root", "js", CreateMode.PERSISTENT);
    }
②、获取节点数据
    /**
     * 获取节点数据
     */
    private static void getDataSync(ZkClient zk) throws InterruptedException, KeeperException {
    
    
        /**
         * 参数一:znode名称
         */
        String res = zk.readData("/root");
        System.out.println(res);
    }
③、更新节点数据
    /**
     * 修改节点数据
     */
    private static void setDataSync(ZkClient zk) throws KeeperException, InterruptedException {
    
    
        /**
         * 参数一:节点名称
         * 参数二:节点数据
         */
        zk.writeData("/root", "javascript");
    }
④、删除节点
    /**
     * 删除节点
     */
    private static void deleteSync(ZkClient zk) throws KeeperException, InterruptedException {
    
    
        /**
         * 参数一:节点名称
         */
        zk.delete("/root");
    }
⑤、获取子节点
    /**
     * 获取所有节点
     */
    private static void getNodesSync(ZkClient zk) throws KeeperException, InterruptedException {
    
    
        /**
         * 参数一:节点名称
         */
        List<String> childrens = zk.getChildren("/");
        childrens.forEach(System.out::println);
    }

节点的监听

①、监听节点
    /**
     * 监听节点
     */
    private static void watcherNodeSync(ZkClient zk) throws InterruptedException, KeeperException {
    
    
        /**
         * 参数一:监听节点信息
         * 参数二:回调函数
         */
        zk.subscribeChildChanges("/", (arg0, arg1) -> {
    
    
            System.err.println("子节点发生变化:" + arg0);
            arg1.forEach(f -> {
    
    
                System.out.println("content:" + f);
            });
        });
        Thread.sleep(Long.MAX_VALUE);
    }
②、监听数据
    /**
     * 监听数据
     */
    private static void watcherDataSync(ZkClient zk) throws InterruptedException, KeeperException {
    
    
        /**
         * 参数一:监听节点名
         * 参数二:回调函数
         */
        zk.subscribeDataChanges("/root", new IZkDataListener() {
    
    
            @Override
            public void handleDataDeleted(String arg0) throws Exception {
    
    
                System.err.println("数据删除:" + arg0);
            }
            @Override
            public void handleDataChange(String arg0, Object arg1) throws Exception {
    
    
                System.err.println("数据修改:" + arg0 + "------" + arg1);
            }
        });
        Thread.sleep(Long.MAX_VALUE);
    }

version3.0

Curator是 Netflix公司开源的一套ZooKeeper客户端框架。和ZkClient一样,Curator解决了很多ZooKeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等,目前已经成为了Apache的顶级项目,是全世界范围内使用最广泛的ZooKeeper客户端之一。

  • Curator包
  1. curator-framework:对zookeeper的底层api的一些封装。
  2. curator-client:提供一些客户端的操作,例如重试策略等。
  3. curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等。

导入依赖

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

配置文件

    public static void main(String[] args) {
    
    
        /**
         * 参数一:zookeeper 地址,多个用逗号隔开
         * 参数二:超时时间
         * 参数三:重试机制
         */
        CuratorFramework cur = CuratorFrameworkFactory.builder()
                .connectString("ip:2181")
                .connectionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                .build();
        cur.start(); //连接zookeeper
    }

操作zookeeper

节点操作

  • znode 类型有四种:
类型 含义
PERSISTENT 持久化目录节点,客户端与zookeeper断开连接后,该节点依旧存在
PERSISTENT_SEQUENTIAL 持久化,并带有序列号
EPHEMERAL 临时目录节点,客户端与zookeeper断开连接后,该节点被删除
EPHEMERAL_SEQUENTIAL 临时,并带有序列号
①、创建节点
    /**
     * 创建节点
     */
    private static void createNodeSync(CuratorFramework curatorFramework) throws Exception {
    
    
        curatorFramework.create()
                .withMode(CreateMode.PERSISTENT) // 节点类型:持久节点
                /**
                 * 参数一:节点名称
                 * 参数二:节点数据
                 */
                .forPath("/root", "itxiong".getBytes());
    }
②、获取节点数据

读取一个节点的数据内容,同时获取到该节点的stat

    /**
     * 获取节点数据
     */
    private static void getDataSync(CuratorFramework cur) throws Exception {
    
    
        Stat stat = new Stat();
        byte[] bytes = cur.getData()
                .storingStatIn(stat) // 获取节点信息状态(可省略)
                .forPath("/root"); // 节点名
        System.out.println(new String(bytes));
        System.out.println(stat);
    }
③、更新节点数据
    /**
     * 修改节点数据
     */
    private static void setDataSync(CuratorFramework cur) throws Exception {
    
    
        Stat stat = cur.setData()
                .withVersion(10086) // 指定修改的版本(可省略)
                /**
                 * 参数一:节点名称
                 * 参数二:修改数据
                 */
                .forPath("/root", "data".getBytes());
        System.out.println(stat);
    }
④、删除节点
    /**
     * 删除节点
     */
    private static void deleteSync(CuratorFramework cur) throws Exception {
    
    
        cur.delete()
                .deletingChildrenIfNeeded()// 删除一个节点,并且递归删除其所有的子节点
                .withVersion(10086) // 强制指定版本进行删除
                .forPath("/root");
    }
⑤、获取子节点
    /**
     * 获取所有节点
     */
    private static void getNodesSync(CuratorFramework cur) throws Exception {
    
    

        List<String> list = cur.getChildren().forPath("/");
        list.forEach(System.out::println);
    }
⑥、节点是否存在
    /**
     * 检查节点是否存在
     */
    private static void isNodeExists(CuratorFramework cur) throws Exception {
    
    
        cur.checkExists().forPath("/root");
    }

节点的监听

①、监听数据
    /**
     * 监听节点数据
     */
    private static void watcherDataSync(CuratorFramework cur) throws Exception {
    
    
        /**
         * 参数一:zookeeper对象
         * 参数二:节点名
         */
        NodeCache nodeCache = new NodeCache(cur, "/node1");
        nodeCache.getListenable().addListener(() -> {
    
    
            System.out.println("被修改了。。。。。");
        });
        // 开启监听
        nodeCache.start();
        Thread.sleep(Long.MAX_VALUE);
    }

三、Zookeeper(Dubbo)操作-SpringBoot

version1.0

导入依赖

    <dependencies>
        <!-- Dubbo 依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>
        <!-- zookeeper 注册中心 依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>2.7.6</version>
            <!--排除日志SLF4J防止冲突-->
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

配置文件

# 端口号
server:
  port: 9090
# dubbo 配置
dubbo:
  # 服务名配置
  application:
    name: rpc-provider
  # 注册配置
  registry:
    # 单机
    address: zookeeper://ip:2181
    # 集群
    #    address: zookeeper://0.0.0.0:2181?backup=127.0.0.1:2182,192.168.0.1:2183
    # 超时时间
    timeout: 50000
  # 协议端口
  protocol:
    name: dubbo
    port: 20880
  # 注册文件位置
  scan:
    base-packages: com.xl.service.impl

使用Dubbo

生产者-@Service

  • @Service

import org.apache.dubbo.config.annotation.Service;

@Service参数表
@Service参数 含义 实例
timeout 设置超时机制,超时时间(ms) @Service(timeout = 3000) //当前服务3秒超时
retries 设置超时重试机制,重试次数 @Service(timeout = 3000,retries = 2)
version 设置服务版本,x.x.x @Service(version = “2.0.0”)
loadbalance 设置负载均衡方式 @Service(timeout = 3000,retries = 3,loadbalance = “roundrobin”)
executes 服务限流-并发控制,最大并发数 @Service(executes = 10)
actives 服务限流-连接控制,最大连接 @Service(actives= 10)
负载均衡相关参数
参数 含义
random 随机负载均衡,随机的选择一个,默认负载均衡。
roundrobin 轮询负载均衡。
leastactive 最少活跃调用数,相同活跃数的随机。
consistenthash 一致性哈希负载均衡,相同参数的请求总是落在同一台机器上。
示例
@Service
public class OrderServiceImpl implements IOrderDubboService {
    
    
    /**
    * 业务内容
    */
}

消费者-@Reference

  • @Reference

import org.apache.dubbo.config.annotation.Reference;

@Reference参数表
@Reference参数 含义 实例
timeout 设置超时机制,超时时间(ms) @Reference(timeout = 2000)// 远程注入,一方设置即可
version 设置使用的服务版本,x.x.x @Reference(version = “2.0.0”)
loadbalance 设置负载均衡方式 @Reference(timeout = 2000,loadbalance = “roundrobin”)
cluster 集群容错 @Reference(cluster = “failover”)
mock 服务降级 @Reference(timeout = 2000,mock = “force:return null”)
cache 缓存机制 @Reference(cache = “lru”) //结果缓存
①、负载均衡
参数 含义
random 随机负载均衡,随机的选择一个,默认负载均衡。
roundrobin 轮询负载均衡。
leastactive 最少活跃调用数,相同活跃数的随机。
consistenthash 一致性哈希负载均衡,相同参数的请求总是落在同一台机器上。
②、集群容错
容错模式 含义
failover 失败重试。默认值。一般用于读操作。
failfast 快速失败,只发起一次调用,失败立即报错。通常用于写操作。
failsafe 失败安全,出现异常时,直接忽略。返回一个空结果。日志不重要操作。
failback 失败自动恢复,后台记录失败请求,定时重发。非常重要的操作。
forking 并行调用多个服务器,只要有一个成功即返回。
broadcast 广播调用所有提供者,逐个调用,任意一台报错则报错。 同步要求高的可以使用这个模式。
③、服务降级
降级方式 含义
mock=force:return null 表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。
mock=fail:return null 表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。
④、缓存机制
缓存方式 意义
lru 保持最新
threadlocal 当前线程缓存
jcache 桥接缓存
示例
@Service
public class UserServiceImpl implements IUserService {
    
    
    //引入订单服务
    @Reference
    IOrderDubboService iOrderService;
    /**
     * 根据用户id查询订单
     * @param id 用户id
     * @return
     */
    @Override
    public CommonResult<Order> findByUserId(Long id) {
    
    
        CommonResult commonResult = new CommonResult();
        commonResult.setCode(200);
        commonResult.setMessage("查询成功");
        //远程调用
        CommonResult<Order> orderCommonResult = iOrderService.findByuserId(id);
        commonResult.setData(orderCommonResult);
        return commonResult;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_56571862/article/details/128714027