分布式调用与高并发处理 Zookeeper分布式协调服务(四)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 分布式调用与高并发处理 Zookeeper分布式协调服务(四)

五、zkClient操作Zookeeper

使用zookeeper遇到问题:

  • 重复注册watcher
  • session失效重连
  • 异常处理(删除节点不能有子节点,新增节点必须有父节点等)

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

添加依赖

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

创建会话

//1.创建会话
  ZkClient zkClient = new ZkClient("192.168.66.100:2181,192.168.66.101:2181,192.168.66.102:2181");

创建节点

//3.创建节点
 zkClient.create("/zkTest/zkTest3","3", CreateMode.PERSISTENT);

获取/zkTest子节点

//2.获取/zkTest子节点
List<String> children = zkClient.getChildren("/zkTest");
children.forEach(System.out::println);

修改节点数据

zkClient.writeData("/zkTest/zkTest3","4");

获取节点数据

//5.获取节点数据
 String data = zkClient.readData("/zkTest/zkTest3");

删除节点

//6.删除节点
zkClient.delete("/zkTest/zkTest3");

注册节点监听事件

//7.注册节点监听事件
        zkClient.subscribeChildChanges("/zkTest",new IZkChildListener(){
            @Override
            public void handleChildChange(String s, List<String> list) throws Exception {
                System.out.println("节点改变了");
                list.forEach(System.out::println);
            }
        });

注册数据监听事件

//8.注册数据监听事件
        zkClient.subscribeDataChanges("/zkTest", new IZkDataListener() {
            @Override
            public void handleDataChange(String s, Object o) throws Exception {
                System.out.println("数据改变了");
            }
            @Override
            public void handleDataDeleted(String s) throws Exception {
                System.out.println("数据删除了");
            }
        });

六、ApacheCurator操作Zookeeper

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

Curator包

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

添加Maven依赖

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

创建会话

//1.创建会话
        String connStr = "192.168.66.100:2181,192.168.66.101:2181,192.168.66.102:2181";
        CuratorFramework cur= CuratorFrameworkFactory.builder()
                .connectString(connStr)
                .connectionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000,3)) //断开重试机制
                .build();
        //2.连接
        cur.start();连接

创建节点

//3.创建节点
     cur.create().withMode(CreateMode.PERSISTENT).forPath("/zkTest/zkTest4","4".getBytes());

获取数据

//4.获取数据
        byte[] bytes = cur.getData().forPath("/zkTest/zkTest4");
        System.out.println(new String(bytes));

删除一个节点

//5.删除节点
        cur.delete().forPath("/zkTest/zkTest4");

注意:

此方法只能删除叶子节点,否则会抛出异常。

删除一个节点,并且递归删除其所有的子节点

cur.delete().deletingChildrenIfNeeded().forPath("/zkTest");

更新一个节点的数据内容

client.setData().forPath("path","data".getBytes());

监听节点

//8.监听机制
        NodeCache nodeCache = new NodeCache(cur, "/zkTest/zkTest3");
        nodeCache.getListenable().addListener(()-> System.out.println("被修改"));
        nodeCache.start();

七、Zookeeper高级

7.1 四字命令

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

添加配置(前提)

vim zoo.cfg
#开启四字命令
4lw.commands.whitelist=*
#添加nc命令
yum install nc -y

conf

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

echo conf| nc localhost 2181

注意:

注意,conf命令输出的配置信息仅仅是输出一些最基本的配置参数。另外,conf命令会根据当前的运行模式来决定输出的信息。如果是单机模式(standalone), 就不会输出诸如initLimit.syncLimit、electionAlg 和electionPort等集群相关的配置信息。

cons

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

echo cons | nc localhost 2181

ruok

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

echo ruok | nc localhost 2181

stat

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

echo stat | nc localhost 2181

注意:

除了一些基本的状态信息外,stat命令还会输出一些服务器的统计信息,包括延迟情况、收到请求数和返回的响应数等。注意,所有这些统计数据都可以通过srst命令进行重置。

mntr

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

echo mntr | nc localhost 2181

7.2 选举机制

核心选举原则

  • Zookeeper集群中只有超过半数以上的服务器启动,集群才能正常工作;
  • 在集群正常工作之前,myid小的服务器给myid大的服务器投票,直到集群正常工作,选出Leader;
  • 半数机制;

选举机制流程

  • 服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking(选举状态)。
  • 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING。
  • 服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为领导者,服务器1,2成为小弟。
  • 服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为小弟。
  • 服务器5启动,后面的逻辑同服务器4成为小弟。

选择机制中的概念

Serverid:服务器ID

比如有三台服务器,编号分别是1,2,3。

编号越大在选择算法中的权重越大。

Zxid:数据ID

服务器中存放的最大数据ID.

值越大说明数据越新,在选举算法中数据越新权重越大。

Epoch:逻辑时钟

或者叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断。

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
2月前
|
监控 NoSQL Java
分布式锁实现原理问题之ZooKeeper的观察器(Watcher)特点问题如何解决
分布式锁实现原理问题之ZooKeeper的观察器(Watcher)特点问题如何解决
|
1月前
|
存储 监控 Java
近亿级用户体量高并发实战:大促前压测干崩近百个服务引起的深度反思!
几年前,数百个服务,将堆内存从28GB升配到36GB,引发系统全面OOM的事件。
72 12
|
2月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
61 3
|
1月前
|
Java 应用服务中间件 数据库
SpringCloud:服务保护和分布式事务详解
SpringCloud:服务保护和分布式事务详解
92 0
|
2月前
|
算法 前端开发
|
2月前
|
NoSQL 前端开发 算法
Redis问题之Redis分布式锁与Zookeeper分布式锁有何不同
Redis问题之Redis分布式锁与Zookeeper分布式锁有何不同
|
2月前
|
存储 安全 Java
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
49 0
|
2月前
|
存储 Java Spring
使用Spring Boot和Zookeeper实现服务协调
使用Spring Boot和Zookeeper实现服务协调
|
2月前
|
安全 Java
使用Zookeeper实现分布式锁的最佳实践
使用Zookeeper实现分布式锁的最佳实践
|
2月前
|
缓存 Java 数据库连接
使用Java构建一个高并发的网络服务
使用Java构建一个高并发的网络服务