首页 > 其他分享 >Zookeeper Session原理

Zookeeper Session原理

时间:2023-04-02 22:59:11浏览次数:47  
标签:ZooKeeper 过期 Zookeeper SessionId Session 原理 服务端 客户端

我们的 Leader 已经选举出来了,那接下来该干什么呢?你或许很快能想到,那就是数据同步。通俗地讲,就是 Leader 选出来了,各自的角色都确定好了,那 Follower 和 Observer 自然要同 Leader 建立连接同步数据,这里就引入了 ZooKeeper 的另一个核心知识:Session。

一、什么是 Session?

Session 的概念大家都不陌生,学过 Servlet 的同学一定都背过一道面试题:Cookie 和 Session 的区别是什么?我通过一个案例来阐述下。

我们都知道浏览器打开一个页面采取的是 HTTP 协议,HTTP 的特点就是无状态,也就是说每一次请求之间没有任何关联,这样的好处肯定是,但是也带来了一个问题。举个最简单的例子:评论功能需要先登录,那么我登录是 https://www.xxx.com/login.html,登录完后跳转到了帖子页面https://www.xxx.com/111.html,这两页面完全不是一个东西,而 HTTP 又是无状态的,所以即使我登录成功了,也无法将登录态带到帖子页面,我在帖子页面评论的时候仍然会被认为是未登录的。

这咋办呢?这时候 Cookie 就诞生了,Cookie就是把少量的信息存到用户自己电脑上,也就是存储在客户端Cookie 的作用域是在一个域名下都可以获取到,因为我们可以在登录后将用户登录态存储到www.xxx.com这个域名下,然后在访问其他页面的时候都先读一下 Cookie,这样就解决了 HTTP 无状态所带来的这个登录态的问题

这一切看起来都很完美,但是问题在于 Cookie 是存储在客户端的,而且 Cookie 存储的内容是有大小限制的,所以上面我说存储少量的信息到用户自己电脑上。这就带来很多问题了,比如:用户浏览器设置的自动清除 Cookie,那这样不就完犊子了吗?再比如:Cookie 是存到用户自己电脑上,那岂不是可以随意修改?信息不安全啦。

好吧,Cookie 的生涯只能结束了,Session 应运而生,这也是要出现 Session 的主要原因。

其实,Cookie 的主要问题就在于它存储在客户端,那我们 Session 存储在服务端不就好了吗?存储在服务端,大小可控而且安全。我们在服务端生成 Session,然后为其生成一个对应的 SessionId 返回给客户端,通信期间带上 SessionId 做唯一标识符,也就是说一个用户生成一个一个 SessionId,贯穿整个请求。当然 Session 还有很多其他特性,比如 Session 带过期时间、带垃圾回收等内容,这些感兴趣的小伙伴可以自行了解下~

Session 是什么以及为什么要有 Session,想必你已经很清楚了。那我们接下来就步入正题,看看 ZooKeeper 的 Session 又是什么。

二、ZooKeeper 的 Session

老规矩,我们不会直接剖析 ZooKeeper 现有的 Session 源码,而是先剖析其原理、核心思想以及核心交互流程,搞懂这些后我们再剖析源码会事半功倍。所以,你可以把本篇文章想象成为一个需求文档的分析与设计的过程,首先我们需要搞懂需求,也就是需求分析:ZooKeeper 的 Session 是什么?什么时候需要用到 Session?

我们已经知道 Session 是会话的意思,我们还知道了 Leader 选举的全过程以及选举完成后接下来要做什么事情(数据同步),数据同步自然是需要通过网络来完成,也就是需要客户端与 ZooKeeper 服务端建立连接进行网络通信传输数据,这里我们就需要用到 Session。我们还知道 ZooKeeper 客户端可以进行 CRUD,需要和服务端建立连接,这时候也需要产生一个 Session,代表客户端和服务端的一次通信会话

那要如何设计这个 Session 呢?

我们可以先采取笼统的方式概括出 Session 的几个核心必备功能,然后再逐个展开分析。

Session 首先要有 SessionId,这个 SessionId 和 HTTP 的 Session 是一个道理,都是用于客户端和服务端通信之间产生 Session 的唯一标识。举个例子:现在 Leader 选举完成了,大家都知道谁是 Leader、谁是 Follower 了,那么 Follower 要和 Leader 建立网络连接进行数据同步,这时候服务端就会创建一个 Session 并且产生一个 SessionId,然后记录下来。大致情况如下图所示:

image.png

那 Session 什么时候结束?很简单想到,客户端和服务端断开连接的时候结束,所以这时候就有两种情况:客户端主动向服务端发信号断开和服务端主动向客户端发信号断开,但是这样就靠谱了吗?我们想想我们的各种连接,比如 HTTP 连接、数据库连接、Redis 连接等,都会设置一个超时时间,防止长时间占用资源不使用的情况,避免资源浪费。我们 Session 也同理,需要有个过期时间,便于我们找出要过期的客户端连接,给释放掉。所以,我们在创建 Session 的时候要为其设置一个过期时间,如下图:

image.png

那我们怎么知道 3s 后有哪些 Session 过期呢?我们肯定需要一个“定时任务”,定时去扫描一次,看看有哪些过期的 Session,然后将其销毁,释放连接。我们 ZooKeeper 配置文件zoo.cfg就有这样的一个配置项:tickTime,这个配置项就是配置多少毫秒检测一次。假设我们配置的是 3000 毫秒,SessionId 为 111 的过期时间为 6000 毫秒,那么如下时间轴:

image.png

按照上图所示,当前时间轴处于1231000位置,每隔 3000ms 就检查一次,意味着 6000ms 后(执行两次后),会扫描到SessionId111过期,然后将其 Session 回收,以及连接断开。

那这时候问题来了,我们知道 ZooKeeper 有个tickTime配置用于设置间隔多久检查一次,如果 Session 的过期时间不是tickTime设置值的倍数会咋样?如下图:

image.png

这样的话,看起来 Session 的过期时间不准确,实际的过期时间会大于等于所设置的过期时间。比如,上面图的含义是SessionId=222的 Session 以为自己在时间轴为1235000的时候就过期了,但是实际在1235000的时候没有触发扫描任务,在1237000的时候才会扫描,因此它的实际过期时间为1237000

这样不太友好,ZooKeeper 采取的手法是按照tickTime的倍数生效。也就是说,比如tickTime设置的是 3000ms,而且SessionId=1设置的是 4000ms 过期,那么SessionId=1的实际过期时间就是 6000ms 的位置;再比如SessionId=2设置的是 8000ms 过期,那么SessionId=2的 Session 实际过期时间是 9000ms 的位置。那如果SessionId=3设置的 2000ms 过期呢?那对不起,这个SessionId=3实际过期时间就是 3000ms。完整情况如下图:

image.png

所以,Session 过期时间建议设置成tickTime的倍数,即使不这么设置的话,那实际的过期时间也是tickTime的倍数

但如果这样设计的话还是会有 Bug,比如SessionId=1 的 Session 设置的超时时间是 2000ms,现在假设这个 Session 处理时长超过了 2000ms,那么它下次再次使用的时候就需要重新建立连接吗?这显然不妥,连接的建立是很耗时且耗费资源的,因此我们需要一个续期的功能,只要客户端做操作(CURD),那么服务端就会刷新该客户端对应 Session 的过期时间。如下图:

image.png

再想另外一种场景:我们客户端与服务端建立连接后如果不是手动销毁或者意外宕机等情况,我们是希望一直持有连接的,这样可以避免频繁创建、销毁连接这种影响性能的操作。那么客户端和服务端怎么彼此知道对方是否存活呢?单独靠需要操作(CRUD)的时候再去感知是不靠谱、也不优雅的,我们需要定时发 ping 请求去探活,也就是心跳机制每次心跳正常都会更新此客户端对应 Session 的过期时间,这样来一直维活

这里举个例子。假设我们声明一个 ZooKeeper 客户端,过期时间是 3000ms:

ZooKeeper client = new ZooKeeper("127.0.0.1:2181", 3000, null);

那么,客户端每隔一段时间就会进行心跳检测的,比如每隔 1000ms 检测一次,那么只要客户端和服务端都正常通信的话,客户端会每隔一秒给服务端发一个 ping 请求,服务端收到后会更新此请求对应的 Session 过期时间。

三、总结

Session 相关的原理部分我们到此结束了。其实本篇内容是很轻松愉快的,没有很复杂的逻辑在里面,最后我们做个总结。

我们先讲解了 HTTP Session 的由来以及概念,然后从 0 到 1 分析了 ZooKeeper Session 的用途以及一些原理。原理部分我们主要涉及到如下内容。

  1. Session 是干什么的?什么时候需要创建 Session?我们有提到一个客户端的连接就对应一个 Session 的产生,Session 主要用于客户端与服务端之间通信

  2. 采取 SessionId 来标记出这个 Session 的唯一性,但是 SessionId 是根据什么算法或者什么规则生成的呢?这个我们留到下一篇源码剖析当中去讲解。

  3. 我们还讲解到 Session 的特性:过期机制。讲解了 Session 过期时间的规则和注意事项,比如:最好设置成tickTime的整数倍,即使没设置成整数倍,那么实际过期时间也是倍数的。

  4. 我们还提及到防止 Session 过期时间太短,导致业务没执行完,客户端和服务端之间就断开连接的情况,我们会有两种刷新 Session 过期时间机制:正常业务操作(CRUD)以及心跳机制

相信小伙伴有很多疑问,比如:SessionId 生成算法是什么?每隔 tickTime 去扫描过期的 Session 然后释放资源,那么 Session 以及过期时间是如何管理的?再比如:如果客户端宕机了,那么服务端怎么处理这个 Session?假设服务端宕机了,那么客户端该怎么办?这些我们都放到 Session 机制底层源码剖析里去讲解。

标签:ZooKeeper,过期,Zookeeper,SessionId,Session,原理,服务端,客户端
From: https://www.cnblogs.com/fxh0707/p/17281649.html

相关文章

  • 【深度学习时间序列预测案例】零基础入门经典深度学习时间序列预测项目实战(附代码+数
    前言......
  • 基于3.5.x 版本进行zookeeper 集群搭建
    搭建zk3.5.x版本的集群环境本次搭建使用3.5.7版本的zk。3.5.x版本进行集群环境的搭建,本质其实和3.4.x是没有太大区别的。但是3.5.x的集群环境支持动态的扩缩容,因此在配置文件方面,将集群节点的配置单独抽取出来了,存放到一个zoo.cfg.dynamic的配置文件中。解压安......
  • 基于3.4.x 版本进行zookeeper 集群搭建
    搭建一主二从三个节点zookeeper集群环境***使用zk的3.4.13的版本***注意:对于zk,3.4版本和3.5版本集群环境是有一些区别的。3.5版本以后使用的是动态集群模式,支持集群的动态扩缩容。(可以在不重启的情况下,实现集群的扩容,缩容)本集群搭建使用的是3.4的版本,后......
  • Elasticsearch 学习- 分片原理,倒排索引,文档搜索,文档分析,内置分析器,指定分词器,IK分词器
    Elasticsearch学习-分片原理4.6分片原理​ 分片是Elasticsearch最小的工作单元。但是究竟什么是一个分片,它是如何工作的?​ 传统的数据库每个字段存储单个值,但这对全文检索并不够。文本字段中的每个单词需要被搜索,对数据库意味着需要单个字段有索引多值的能力。最好的支......
  • “通信原理研讨会”之后的一些思考
    大家好,我是小枣君。上周六,东南大学联合人民邮电出版社,在北京共同主办了一场“通信原理”课程研讨会。该研讨会邀请了包括北邮、国防科大、成电、西电在内的国内众多高校通信原理课程一线教师,共同参与教学内容研讨、教学经验交流。研讨会的演讲嘉宾,都是国内顶尖高校的顶级专家,相信很......
  • Tomcat 入门实战(4)--Tomcat 集群 Session 复制
    本文主要介绍在Tomcat集群中如何进行Session复制,文中所使用到的软件版本:Centos7.9.2009、Java1.8.0_321、Tomcat8.5.87。1、快速配置取消conf/server.xml文件中的以下注释来启用集群:<ClusterclassName="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>使用上述配......
  • Thanos工作原理及组件简介
    Thanos简介Thanos是一个「开源的,高可用的Prometheus系统,具有长期存储能力」。很多知名公司都在使用Thanos,也是CNCF孵化项目的一部分。Thanos的一个主要特点就是通过使用对象存储(比如S3)可以允许“无限”存储空间。对象存储可以是每个云提供商提供的对象存储也可以是c......
  • 生活中的常识与原理001-天文-基础
    相关英文词汇:latitude/ˈlætɪtjuːd/,纬度,记忆时可以与ladder相关联,因为纬度是标识南北的线,就像梯子的格子一样。赤道为0度,北极为90度。注意与高度altitude相区别。longitude/ˈlɔndʒɪtjuːd/,经度。从南到北,与赤道垂直。0度经线贯穿英国格林尼治天文台。经度和纬度可以标......
  • 生活中的常识与原理00000-缘起
    在2023年的春分前后,突然对于太阳在空中的运行轨迹有了兴趣,发现太阳东升西落这个让大多数人熟视无睹的现象里,也有很多误解,而且想真正弄清背后的原理还真的很费脑筋。比如在不同城市的人们看到太阳在空中的运动轨迹是一样的吗?一年中的每一天都是一样的吗?有什么规律?而且我也逐渐感......
  • java 中required_通过实例学习Spring @Required注释原理
    @Required注释应用于bean属性的setter方法,它表明受影响的bean属性在配置时必须放在XML配置文件中,否则容器就会抛出一个BeanInitializationException异常。下面显示的是一个使用@Required注释的示例。示例:让我们使EclipseIDE处于工作状态,请按照下列步骤创建一个......