带着问题撸源码系列-zookeeper-临时节点[ephemeral]是怎么弄的?我写了一堆临时节点为啥我一掉线就全没了?
问题
带着问题撸源码系列-zookeeper-临时节点[ephemeral]是怎么弄的?我写了一堆临时节点为啥我一掉线就全没了?
猜测
可能是有线程维护着,每个session有一个临时节点列表,一旦客户端不再发心跳就全干掉
源码
我们可以看到,在DataTree里确实有以sessionid为key的这么个ConcurrentHashMap。
debug
run server 1(follower)
debug server 2 (leader)
client 请求server2: create -e /t1
我们可以直接出绝招,把断点打在创建临时节点的底层代码那里:
org.apache.zookeeper.server.DataTree#createNode(java.lang.String, byte[], java.util.List<org.apache.zookeeper.data.ACL>, long, int, long, long, org.apache.zookeeper.data.Stat)
然后我们请求就可以看到调用栈了:
一步到位,酸爽。我们可以从这里发现什么信息呢?
1、传入的ephemeralOwner是sessionid,=-1代表不是ephemeral节点
2、最终临时节点是写到ephemerals
里的
然后我们看看是怎样做到客户端一掉线,临时节点就全没了的:
老办法,我们在deleteNode直接打断点,看是怎么触发的:
我们用客户端先
create -e /e1
然后
close
就触发了断点,轻松又愉快地找到了调用栈:
可以看到,实际上也是走的leader的职责链
相当于给leader发了一个closeSession的命令
最终就会走到deleteNode函数。
这的确最终是删除了/e1
节点,不过从调用栈还是没有解决我们的问题,是谁发出的请求要删掉这个/e1
节点呢?
鉴于所有给leader的请求都是走职责链的,所以我们从最开始的PrepRequestProcessor看是怎么处理close session的。
找着找着我们看到了org.apache.zookeeper.server.PrepRequestProcessor#pRequest2Txn
这里面就是把当前session里的ephemeral 节点找出来,每个加到record里,然后估计又会有地方消耗这个queue:
咱们的FinalRequestProcessor
会来清空queue。每次Request都会走到FinalRequestProcessor
所以肯定能处理到这个请求。
于是就回到咱们刚才那个调用栈了。
其实还有问题。如果不是主动关闭session,而是断线了呢?
我们在看代码的过程中可以看到有个session expiration thread
大概率就是跟这个有关系。我们可以找相关的代码瞅一瞅。
我们搜索下expriation 找到了这个:
按照注释,就是用这个ExpiryQueue来track的
按时间排序的,固定间隔的buckets。
什么鬼?
再仔细看看这个sessionExpiryQueue
是个什么结构。
sessionExpiryQueue: 包含成员:
eleMap: ConcurrentHashMap key是SessionImpl,value是个时间
expiryMap: ConcurrentHashMap key是时间,value是个set,里面放了过期的SessionImpl。
SessionTrackerImpl
有用到,那我们就去看看呗
有预感这里有一些奇妙的数据结构和算法。
看到这是一个线程,那就直接看他的run方法。(可以预计这是在某个初始化的时候启动了这个线程)
死循环在跑。每次从sessionExpiryQueue获取等待时间,如果还需要等,那就睡一会。否则从队列中哪一个出来。设置session关掉。
poll的时候,目的是要获取过期的session 列表。
获取当前时间,如果还没到点,就返回空列表。
如果到点了,那就设置一个下一次过期的时间,并把这一次过期的列表拿出来返回。
所以这个队列又是谁在往里放?
回答问题
看了这些,我们可以总结出整体思路。
1、每次session发心跳了,我们就更新一下这个数据结构。调用update方法,把当前session的过期时间更新一下。(这里细节是不能直接+interval,而是需要round一下,因为这个将作为key保存那些即将过期的session)
2、有一个线程不停地尝试从队列里poll,如果找到过期的session,那就查找出session对应的那些ephemeral,delete node。
poll的细节是,保存一个”下一次过期时间”nextExpirationTime
。如果当前时间已经超过了nextExpirationTime
那就以这个为key去拿出session set,这个session set就是过期的session列表。
带着问题撸源码系列-zookeeper-临时节点[ephemeral]是怎么弄的?我写了一堆临时节点为啥我一掉线就全没了?相关推荐
- 带着问题读源码-soul(2021-01-16)
### 带着问题读源码系列之Dubbo插件 像往常一样启动 [soul-admin] 和 [soul-bootstrap] . 因为dubbo需要依赖zookeeper, 需要需要启动一个监听在 lo ...
- 带着问题读源码-soul(2021-01-14)
下载编译 git clone git@github.com:dromara/soul.gitcd soulmvn clean package install -Dmaven.test.skip=tru ...
- 带着问题读源码-soul(2021-01-15)
带着问题读源码系列-soul的本地服务筛选 在上一期中,了解到soul的http请求是通过dividePlugin插件完成对本地服务的筛选. 总体来说,可以分为两步: 1. 选出符合调用要求的服务列表 ...
- 源码系列第1弹 | 带你快速攻略Kafka源码之旅入门篇
大家过年好,我是 华仔, 又跟大家见面了. 从今天开始我将为大家奉上 Kafka 源码剖析系列文章,正式开启 「Kafka的源码之旅」,跟我一起来掌握 Kafka 源码核心架构设计思想吧. 今天这篇我 ...
- java 源码系列 - 带你读懂 Reference 和 ReferenceQueue
java 源码系列 - 带你读懂 Reference 和 ReferenceQueue https://blog.csdn.net/gdutxiaoxu/article/details/8073858 ...
- 源码解读_入口开始解读Vue源码系列(二)——new Vue 的故事
作者:muwoo 转发链接:https://github.com/muwoo/blogs/blob/master/src/Vue/2.md 目录 入口开始解读Vue源码系列(一)--造物创世 入口开始 ...
- c++ map 获取key列表_好未来Golang源码系列一:Map实现原理分析
分享老师:学而思网校 郭雨田 一.map的结构与设计原理 golang中map是一个kv对集合.底层使用hash table,用链表来解决冲突 ,出现冲突时,不是每一个key都申请一个结构通过链表串起 ...
- 手把手带你阅读Mybatis源码(三)缓存篇
点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 前言 大家好,这一篇文章是MyBatis系列的最后一篇文章,前面两篇文章:手把手带你阅读M ...
- 手把手教你如何导入源码,zookeeper为例
要学习zookeeper,不可避免的一项就是zookeeper源码的导入工作.本次使用的idea. 步骤: 安装java就省略啦 手把手教你如何导入源码,zookeeper为例 软件 一,安装idea ...
最新文章
- redis 导出导入详解
- Caffe 编译安装
- golang struct 转map 及 map[string]*Struct 初始化和遍历
- 如何访问Wizard控件里的按钮
- 我的crystal report for asp.net測試通過了
- 前端学习(2818):小程序学习之新建页面
- 三行代码生成验证码并转换成base64
- mqtt 多个订阅者 只允许一个接收_一文读懂物联网的灵魂MQTT
- Vue实例-本地留言板
- sklearn中的xgboost_RF/GBDT/XGBoost/LightGBM简单总结
- 基于Python3爬取百度百科内容(可自己输入关键字)
- android语音唤醒app,breeno助手语音唤醒
- 卫星地面站空间分集的必要性及解决方案
- cesium获取经纬度
- 设计模式(讲的比较好-思路清晰,非泛泛而谈)
- notify() 和notifyAll()区别
- 中国黑色金属行业十四五产量需求及发展战略规划研究报告2021版
- 【PMP考前冲刺题-第一小节(2022.7)】
- 岭南师范学院计算机二级查询,岭南师范学院教务管理系统入口http://d.lingnan.edu.cn/jwc/...
- ESP8266-AP模式作服务器