zookeeper如何管理客户端与服务端之间的链接?(zookeeper sessions)

news2024/12/24 9:11:01

zookeeper客户端与服务端之间的链接用zookeeper  session表示。

zookeeper session有三个状态:

CONNECTING, ASSOCIATING, CONNECTED, CONNECTEDREADONLY, CLOSED, AUTH_FAILED,

NOT_CONNECTED(start时的状态)

1、CONNECTING 

    表明客户端正在与服务端建立连接。当客户端的句柄正在建立时,在java中,也就是ZkClient对象在创建后,到与服务端建立起真正链接的过程中,zookeeper的session状态是connecting。

2、CONNECTED 

    表明客户端与服务端已经建立链接。

3、CLOSE

    表明客户端与服务端之间的链接已经关闭。

当以下四种事件发生时,session的状态就会发生改变。

1、当session处于CONNECTING状态,客户端请求被加入到连接请求队列CONNECTING requests queue,执行成功后,会触发CONNECTED EVENTsession状态为CONNECTED

2、当session处于CONNECTING状态,但是客户端与服务端尝试连接的过程中权限校验不通过,触发AUTH_FAILED event,客户端请求返回AUTH_FAILED,连接建立结束。

3、当连接已经建立,session处于CONNECTED状态时,服务端突然出现故障或其他因素导致链接失效,触发DISCONNECTED event,返回CONNECT_LOSS。客户端重新将请求加入到连接请求队列CONNECTING requests queue,session状态重新变为CONNECTING。此时客户端有两个选择:

       重新向zookeeper集群中的其他服务器发起连接,成功则触发CONNECTED event,session状态变为CONNECTED,不断尝试直到超时则会造成session timeout,触发SESSION_EXPIRED event,请求返回SESSION_EXPIRED ,同时session状态修改为CLOSE

      或者,客户端直接请求关闭连接,返回CONNECTION LOSS,session状态变为CLOSE

整个过程如下图所示:

State transitions

zookeeper 客户端与服务端建立链接时有三个参数,一个是地址串,一个是超时时间timeout,一个是监听器。

地址参数表明客户端向哪个zookeeper server发起连接请求。 

当你使用多个zookeeper server地址时,多个地址用逗号隔开,比如“127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002”,zookeeper客户端会随机连接到某个server上,如果连接失败,客户端会不断连接到其他server地址上,直到成功。

 zkClient = new ZooKeeper("127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002", 2000,null);

当链接建立时,客户端所处的路径便是zookeeper server的根节点"/“。我们知道zookeeper没有相对路径的说法,客户端访问的所有节点都需要是绝对路径。那假设我们的配置信息分开发环境env和生产环境prod。开发环境的配置信息放在/env节点下,生产环境的配置放在/prod下。我们在开发时访问zookeeper的任何节点都需要加上前缀/env或者/prod。这样太麻烦了也容易出错。

于是zookeeper提供了一种方法,让我们可以在链接建立之后,访问的所有节点都相对于某个路径。

我们在连接地址串后面加上地址,比如:

        zkClient = new ZooKeeper("127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/env", 2000,null);

 那么当链接建立后,我们访问getData("/a"),实际上访问的是"/env/a”节点。

zookeeper session建立后,服务端会返回一个64位的session id 与针对这个session id设立的密码给客户端。当客户端所连接的这个服务端出现故障导致DISCONNECT event发生后,客户端将会尝试和其他服务端建立链接。客户端会将之前保存的session id与密码发送给新连接的服务端,以保证会话数据和原来一样。

timeout超时时间

session 的超时时间由zookeeper集群自己管理。超时时间是指当session建立后,客户端多长时间没有与服务端进行交互(包括维持连接的心跳也没有)时,集群认为session失效。zookeeper集群会删除这个会话,并且删除这个会话建立的所有临时节点,同时通知所有监听这些临时节点的zookeeper客户端,当然,对于这个这个被删除会话的客户端而言,在它重新连接上zookeeper集群之前它是收不到这个通知的,毕竟如果这个客户端是正常的,那么它就会和zookeeper集群保持心跳以维持会话。会话超时说明这个客户端断开了链接,哪怕zookeeper集群的功能再强大,它也通知不到这个已经失去联系的客户端。

 timeout时间最小是ticktime的两倍时间,最长是20倍。当客户端设置timeout值小于两倍ticktime时,zookeeper server实际返回的是ticktime的两倍时间。

当客户端所连接的server下线时,只要在timeout时间内,客户端能自动重连上zookeeper集群中的其他server,那么会话就能够保持。

zookeeper推荐由zookeeper客户端去负责重连的事情,直到请求返回session expired,此时我们再在自己的程序里去建立一个新的会话。而不是监听到所连接的server下线就立马去建立新的session,那样容易会发生“羊群效应”,也就是当server下线后,所有之前与这个服务端连接的客户端同时申请建立新的会话,会对zookeeper集群造成很大的压力。

SessionMovedException

这是一个内部异常,一般而言来说,客户端不会见到这个异常。当客户端向server A发起请求时,由于网络原因,在请求到达server时客户端就因为长时间没有收到响应而认为A已经下线,进而向server B建立会话。此时请求到达server A,A检测到会话已经转移,就会关闭与这个客户端的tcp链接。这一切都是由zookeeper在内部完成的,正常情况下客户端不会看到这个错误。

当有两个客户端在重建同一个链接时,其中一个客户端建立起的链接会因为另一个客户端建立起同样的链接而失效,从而重新建立链接。不断反复建立,失效,建立,失效,陷入一个死循环中。

在zookeeper3.5.0后加入一个local session概念。

zookeeper的session的建立与关闭是十分消耗性能的。因为在zookeeper中,所有的写操作都要在法定人数的server端操作成功才会同步到所有server。这是zookeeper的写瓶颈所在。另外,假设zookeeper集群的连接客户端非常多,而客户端仅仅只是连接Observer ZooKeeperServer 去读取数据并不涉及写操作时,只建立本地会话能够大大提升性能。

因此在3.5.0后引入一个local session(本地会话)的概念。local session只存在于与客户端连接的server中。

local session有以下特点:

localSessionsUpgradingEnabled 被禁用时,即local session不允许被升级为全局会话,那么:

1、local session不能建立临时节点

2、当会话丢失时,客户端并不能向集群的其他server重建同样的会话。因此local session只存在于之前所连接的server中。但是,这并不意味着当tcp链接断开后,客户端就只能新建一个session了。只要在timeout时间内,客户端重新连接上同一个server,那么session也能够得到保持。

3、local session的信息只由被连接的server维护,并不会通知到集群leader,同样的,session的状态信息也不会被持久化到磁盘。

4、心跳维持、过期和其他session状态由当前的server维护。

为什么要禁用?

  • 在想要处理大量客户端的大型部署中,我们知道客户端通过观察者进行连接,而观察者应该仅是本地会话。因此,这更像是防止有人意外创建大量临时节点和全局会话的防护措施。

localSessionsUpgradingEnabled 启用时,即local session允许被升级为全局会话,那么local session发生以下情况时会被自动升级为global session(全局会话):

1、当local session创建一个临时节点时,local session会先升级为global session再行创建。为什么创建临时节点就要升级为全局会话呢?原因是临时节点的创建在很大程度上取决于全局会话。从数据一致性的角度出发,那么当local session创建临时节点时,不同节点的数据就会不一致。从管理的角度出发,临时节点的删除依赖于集群中的leader。leader需要知道session的生命周期以便当session结束时能够删除临时节点,但是local session并不被leader知晓。

如果请求升级,则将会话从本地集合中删除,同时保留相同的会话ID。

当客户端请求与服务端A建立session时,服务端A会发送session id和password给客户端,同时提交一个createSession给leader。如果在客户端收到返回数据而leader未接收到createSession时,客户端断开连接重连上服务端B,此时服务端B会拿着客户端给的session id发送一个验证包给leader。如果在验证数据包到达之前leader提交了由A发出的CreateSession,则客户端将可以连接。否则,客户端将使会话过期,因为法定人数尚未得知该会话。此时,如果客户端也尝试再次连接回A,则该会话已从本地会话跟踪器中删除。因此,A将需要将验证数据包发送给领导者。处理过程与B相同。

因果一致性

Zookeeper是否满足因果一致性,需要看客户端的编程方式。

  • 不满足因果一致性的做法

1. A进程向Zookeeper的/z写入一个数据,成功返回

2. A进程通知B进程,A已经修改了/z的数据

3. B读取Zookeeper的/z的数据

4. 由于B连接的Zookeeper的服务器有可能还没有得到A写入数据的更新,那么B将读不到A写入的数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1559765.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vulhub中Apache Solr 远程命令执行漏洞复现(CVE-2017-12629)

Apache Solr 是一个开源的搜索服务器。Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现。原理大致是文档通过Http利用XML加到一个搜索集合中。查询该集合也是通过 http收到一个XML/JSON响应来实现。此次7.1.0之前版本总共爆出两个漏洞:[XM…

金三银四面试题(九):JVM常见面试题(3)

今天我们继续探讨常见的JVM面试题。这些问题不比之前的问题庞大,多用于面试中JVM部分的热身运动,开胃菜,但是大家已经要认真准备。 你能保证GC 执行吗? 不能,虽然你可以调用System.gc() 或者Runtime.gc()&#xff0c…

vue3+threejs新手从零开发卡牌游戏(二十四):添加p2战斗逻辑

用代码模拟p2战斗逻辑,按流程进行步骤拆分: 1.p2抽卡 2.p2召唤怪兽上场 3.p2战斗 其中战斗部分分为几种情况: 情况一:p2场上卡牌由大到小进行排序,按序轮询可以攻击的卡牌,然后攻击p1场上卡牌由大到小…

代码随想录阅读笔记-二叉树【完全二叉树节点个数】

题目 给出一个完全二叉树,求出该树的节点个数。 示例 1: 输入:root [1,2,3,4,5,6]输出:6 示例 2: 输入:root []输出:0 示例 3: 输入:root [1]输出:1 提示&…

玩转Django分页器

一、Pagination 分页器编程步骤 View, 导入django.core.paginator.Paginator类,创建Paginator 对象时,输入qs对象,以及每页显示条数。 接收 URL, 从请求参数中读取page数值 ,通过 paginator.page(page_num) 返回请求页的page_obj…

pyinstaller打包多线程pyqt5程序后,报错,反复弹窗等问题

报错1: Traceback (most recent call last): File “MPL.py”, line 502, in File “Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_multiprocessing.py”, line 45, in _freeze_support ValueError: not enough values to unpack (expected 2, got 1) 报…

绘制空心环形

1.通过几个div拼接绘制空心环形进度条。 通过 -webkit-mask: radial-gradient(transparent 150px, #fff 150px);绘制空心圆 html:<body><div class"circle"><div class"circle-left"></div><div class"circle-left-mask&…

从0开始搭建基于VUE的前端项目(二) 安装和配置element-ui组件库

版本和地址 ElementUI 2.15.14 (https://element.eleme.io/)按需引入的插件 babel-plugin-component(1.1.1) https://github.com/ElementUI/babel-plugin-component 安装 npm install element-ui完整引入(不建议) 这种方式最后打包的源文件很大&#xff0c;造成网络资源的浪…

LeetCode-56. 合并区间【数组 排序】

LeetCode-56. 合并区间【数组 排序】 题目描述&#xff1a;解题思路一&#xff1a;排序&#xff1f;怎么排&#xff1f;当然是排各个区间的左边界&#xff0c;然后判断下一个边界的左边界与结果数组里面的右边界是否重叠。解题思路二&#xff1a;优化解题思路三&#xff1a;0 题…

Vitepress部署到GitHub Pages,工作流

效果&#xff1a; 第一步&#xff1a; 部署 VitePress 站点 | VitePress 执行 npm run docs:build&#xff0c;npm run docs:preview&#xff0c;生成dist文件 第二步&#xff1a; 手动创建.gitignore文件&#xff1a; node_modules .DS_Store dist-ssr cache .cache .temp *…

[html]基础知识点汇总

前言 经过一阵子学习后&#xff0c;把知识点全部提炼了出来&#xff0c;自我感觉比较全和简洁&#xff0c;希望能够帮到大家。 本机实验环境 火狐浏览器&#xff0c;vscode&#xff0c;windows11&#xff0c;程序运行插件&#xff1a;live server html介绍 html--前端语言…

深入PostgreSQL中的pg_global表空间

pg_global表空间的位置 在PG当中&#xff0c;一个实例(cluster)初始化完以后&#xff0c;你会看到有下边两个与表空间相关的目录生成&#xff1a; $PGDATA/base $PGDATA/global 我们再用元命令\db以及相关视图看看相应的表空间信息&#xff1a; postgres# \db …

synchronized 关键字 - 监视器锁 monitor lock

目录 一、1 synchronized 的特性 1、互斥 2、可重入 二、synchronized 使用示例 1、修饰代码块: 明确指定锁哪个对象. 2、直接修饰普通⽅法: 锁的 SynchronizedDemo 对象 3、修饰静态方法: 锁的 SynchronizedDemo 类的对象 我们重点要理解&#xff0c;synchronized 锁…

Java设计模式 | 原型模式

是什么 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。该模式的核⼼思想是基于现有的对象创建新的对象&#xff0c;⽽不是从头开始创建。 结构 抽象原型接口&#xff1a;声明一个克隆自身的方法clone()具体原型类&#xf…

飞书API(2):通过 Python 读取多维表数据

上一篇介绍了怎么通过官方的控制台调用飞书的 API 读取多维表数据&#xff0c;本篇介绍怎么通过 Python 读取多维表数据。 通过 Python 读取多维表主要分两步&#xff1a; 第一步是获取 access_token&#xff1b;第二步是拿 access_token 读取数据。 先说第二步&#xff0c;因…

SQLAlchemy 建立数据库模型之间的关系

常见关系&#xff1a; 一对多关系多对一关系多对多关系一对一关系 一对多关系&#xff08;一个作者&#xff0c;多篇文章&#xff09; ## 一对多关系&#xff0c;单作者-多文章&#xff0c;外键不可少 ## 外键(ForeignKey)总在多的那边定义,关系(relationship)总在单的那边定…

【计算机网络】四层负载均衡和七层负载均衡

前言 1、分层方式 首先我们知道&#xff0c;在计算机网络中&#xff0c;常用的协议分层方式&#xff1a;OSI和TCP/IP&#xff0c;以及实际生产中使用的协议划分方式。 在OSI中&#xff0c;各层的职责如下&#xff1a; 应用层&#xff1a;对软件提供接口以使程序能使用网络服…

CVAE——生成0-9数字图像(Pytorch+mnist)

1、简介 CVAE&#xff08;Conditional Variational Autoencoder&#xff0c;条件变分自编码器&#xff09;是一种变分自编码器&#xff08;VAE&#xff09;的变体&#xff0c;用于生成有条件的数据。在传统的变分自编码器中&#xff0c;生成的数据是完全由潜在变量决定的&…

9.图像中值腐蚀膨胀滤波的实现

1 简介 在第七章介绍了基于三种卷积前的图像填充方式&#xff0c;并生成了3X3的图像卷积模板&#xff0c;第八章运用这种卷积模板进行了均值滤波的FPGA实现与MATLAB实现&#xff0c;验证了卷积模板生成的正确性和均值滤波算法的MATLAB算法实现。   由于均值滤波、中值滤波、腐…

【QT+QGIS跨平台编译】054:【exiv2lib+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、exiv2lib介绍二、文件下载三、文件分析四、pro文件五、编译实践一、exiv2lib介绍 exiv2lib 是一个用于处理图像元数据的开源 C++ 库。它可用于读取、编辑和写入图像文件中的 Exif 元数据(Exchangeable Image File Format,可交换图像文件格式)…