当前位置:   article > 正文

zookeeper原理篇-Zookeeper会话机制(1)

zookeeper原理篇-Zookeeper会话机制(1)
  1. 接下来左移24位,我们可以得到结果:

01000001 100000011 11000100 01001101 11110111 00000000 00000000 00000000,可以看到低位已经把高位补齐,剩下的低位都使用了0补齐

3.右移8位,结果变成了:

00000000 01000001 100000011 11000100 01001101 11110111 00000000 00000000

4.计算机器码标识ID

在initializeNextSession方法中,出现了一个id变量,这个变量就是生成的SID的值,而SID在部署的时候就是我们在myid中配置的值,一般是一个整数,假设此时的值为2,转为64位二进制表示:

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010

此时发现高位几乎都是0,进行左移56位以后,得到值如下:

00000010 00000000 00000000 00000000 00000000 00000000 00000000 00000000

5.将前面第三步和第四步得到的结果进行 | 操作:

可以得到结果为:

00000010 01000001 10000011 11000100 01001101 11110111 00000000 00000000

这个时候我们可以得到一个单机中唯一的序列号ID,整个算法大概可以理解为,先通过高8位确定机器以后,后面的56位按照毫秒进行随机,可以看出来当前的算法!还是蛮严谨的,基本上看不出来什么明显的问题,但是其实也有问题的,其中我们可以看到,zk选择了当前机器时间内的毫秒作为基数,但是如果时间到了2022年4月8号以后, System . currentTimeMillis ()的值会是多少呢?

Date d = new Date (2022-1900 f 3,8);
System. out. p rin tln ( Long. toBinaryString(d .getTime()));

打印出来的结果为:

0000000000000000000000011000000000000100110000010000010000000000

接着我们左移24位以后会发现,这个时候的值依然是个负数,所以我们为了保证不会出现负数的情况,解决方案如下:

public static long initializeNextSession(long id { ) {
long nextSid = 0;
nextSid = (System .currentTim eM illis() « 24) > » 8;
nextSid = nextSid | (id « 5 6 );
return nextSid;
} }

这样就可以避免生成的时候出现负数了

SessionTracker

SessionTracker是Zookeeper中的会话管理器,负责整个zk生命周期中会话的创建管理清理操作,而每一个会话在Sessiontracker内部都保留了三份,大体如下:

1.sessionsWithTimeout这是一个ConcurrentHashMap<Long,Integer>类型的数据结构,用来管理会话的超时时间,这个参数会被持久化到快照文件中去

2.sessionsById是一个HashMap<Long,Integer>类型的数据结构,用于根据sessionId来管理session实体

3.sessionsSets同样也是一个HashMap<Long,Integer>类型的数据结构,用来会话超时的时候进行归档,便于进行会话恢复和管理

会话创建

创建会话的过程,大体可以分为几个步骤,分别是处理ConnectRequest请求、创建会话、处理器链路处理和响应,在zk服务端中,首先是NIOServerCnxn来负责接受来自客户端的会话创建请求,并且进行反序列化工作,然后开始分配超时时间。分配完毕后,会开始创建sessionId,并且将其注册到SessionsById和sessionsWithTimeOut,进行激活,这个时候就可以考虑处理流转。

会话管理

Zookeeper中的会话管理主要是SesssionTracker负责的,内部使用了一个特殊的机制,称之为分桶策略,所谓分桶策略,其实是将类似的会话放在一个区块中进行管理,以便于zookeeper对会话进行不同区块的隔离以及同一区块的统一处理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从图中我们可以看到,所有的会话都分配在了不同的区块中,分配原则是每个会话的下个超时的时间点,ExpiractionTime是指最近一次可能过期的时间点,每一个会话的ExpiractionTime的计算方式如下:

ExpiractionTime = CurrentTime + SessionTimeout

但是不要忘记了,Zookeeper的Leader服务器在运行期间会定期检查是否超时,这个定期的时间间隔为ExpiractionInterval,单位是秒,默认情况下是tickTime的值,即2000毫秒进行一次检查,完整的ExpiractionTime的计算方式如下:

ExpirationTime_ = CurrentTime + SessionTimeout ;
ExpirationTime = (ExpirationTime_ / Expirationlnterval+ 1) x Expirationlnterval ;

会话激活

同样的,在整个zookeeper运行过程中,客户端会在超时时间内向服务端发送PING请求来保持时效性,俗称心跳检测,而服务端在接受到了客户端的心跳请求后需要再次激活会话状态,这个过程称之为TouchSession,流程如下:

1.检验会话是否已经被关闭,Leader会去检查会话是否被关闭,如果已经关闭,不会再去激活该会话

2.如果会话没有被关闭,则开始计算下一次的超时时间Expiration_New,而计算的过程则是使用上面的公式

3.计算完新的超时时间以后,会去获取会员原来的超时时间,并且根据时间来定位原来存放的区块

4.接着,从该区块中找到会话,进行会话迁移,放入新的Expiration_New对应的区块中,如图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

经过以上的步骤,基本已经完成了会话的激活,而每一次心跳的检测,则是进行了一次会话激活操作,在整个Zookeeper运行过程中,一般如下两个操作才会导致会话激活:

1.当客户端向服务端发送请求的时候,包括读写请求,都会主动触发一次会话激活

2.如果客户端在sessionTimeOut / 3时间范围内尚未和服务器之间进行通信,即没有发送任何请求,就会主动发起一个PING请求,去触发服务端的会话激活操作

除此之外,由于会话之间的激活是按照分桶策略进行保存的,因此我们可以利用此策略优化对于会话的超时检查,在Zookeeper中,会话超时检查也是由SessionTracker负责的,内部有一个线程专门进行会话的超时检查,只要依次的对每一个区块的会话进行检查,由于分桶是按照ExpriationInterval 的倍数来进行会话分布的,因此只要在这些时间点检查即可,这样可以减少检查的次数,并且批量清理会话,实现较高的效率。

会话清理

会话检查操作以后,当发现有超时的会话的时候,会进行会话清理操作,而Zookeeper中的会话清理操作,主要是以下几个步骤:

1.由于会话清理过程需要一定的时间,为了保证在清理的过程中,该会话不会再去接受和处理发来的请求,因此,在会话检查完毕后,SessionTracker会先将其会话的isClose标记为true,接着为了保证在进行会话关闭的过程中,在整个集群中都生效,Zookeeper使用了提交的方式,交给PreRequestProcessor处理器进行处理

2.在某个会话失效后,这个会话创建的相关临时节点列表都应该被删除,因此在删除会话之前,需要先找到与改会话相对应的临时节点列表,在Zookeeper的内存数据库中,会为每一个会话单独保存一份由该会话维护的临时节点集合,但是我们需要考虑一些特殊情况,例如在删除会话的时候,有没处理完毕的删除节点的请求,而这个被删除的节点刚好又是会话对应的临时节点,或者这个时候正在处理临时节点创建的请求,而且也是当前会话的请求。这个时候我们必须考虑处理方案,防止出现数据不一致的情况,而第一种情况,则是防止重复删除,我们只需要先把请求对应的节点删除,再去删除对应的列表即可,而第二种情况,我们也需要先执行添加节点的请求,保证节点不会出现删除遗漏即可。

3.当会话对应的临时节点列表找到后,Zookeeper会将列表中所有的节点变成删除节点的请求,并且丢给事物变更队列OutStandingChanges中,接着FinalRequestProcessor处理器会触发删除节点的操作,从内存数据库中删除。

4.当会话对应的临时节点被删除以后,就需要将会话从SessionTracker中移除了,主要从SessionByIdsessionsWithTimeOut以及sessionsSets中将会话移除掉,当一切操作完成后,清理会话操作完成,这个时候将会关闭最终的连接NioServerCnxn

会话重连

在Zookeeper运行过程中,也可能会出现会话断开后重连的情况,这个时候客户端会从连接列表中按照顺序的方式重新建立连接,直到连接上其中一台机器为止,这个时候可能出现两种状态,一种是正常的连接CONNECTED,这种情况是Zookeeper客户端在超时时间内连接上了服务端,而超时以后才连接上服务端的话,这个时候的客户端会话状态则为EXPIRED,被视为非法会话。

而在重连之前,可能因为其他原因导致的断开连接,即CONNECTION_LESS,会抛出异常 org.apache.zookeeper.KeeperException$ConnectionLossException,我们需要捕获异常,并且在重连成功后,收到None-SyncConnection通知里面进行setData的处理操作即可。而在这个过程中,会话可能会出现两种情况:

会话失效:SESSION_EXPIRED

总结

**其实上面说了这么多,钱是永远赚不完的,在这个知识付费的时代,知识技能提升才是是根本!我作为一名8年的高级工程师,知识技能已经学习的差不多。**在看这篇文章的可能有刚刚入门,刚刚开始工作,或者大佬级人物。

像刚刚开始学Android开发小白想要快速提升自己,最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以这里分享一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

这么重要的事情说三遍啦!点赞+点赞+点赞!

【Android高级架构师系统学习资料】高级架构师进阶必备——设计思想解读开源框架

第一章、热修复设计
第二章、插件化框架设计
第三章、组件化框架设计
第四章、图片加载框架
第五章、网络访问框架设计
第六章、RXJava 响应式编程框架设计
第七章、IOC 架构设计
第八章、Android 架构组件 Jetpack


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
pack

[外链图片转存中…(img-b71uMaz0-1715435749302)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/594801
推荐阅读
相关标签
  

闽ICP备14008679号