Tomcat源码分析-Session源码解析
tomcat session 设计分析
tomcat session 组件图如下所示,其中 Context
对应一个 webapp 应用,每个 webapp 有多个 HttpSessionListener
, 并且每个应用的 session 是独立管理的,而 session 的创建、销毁由 Manager
组件完成,它内部维护了 N 个 Session
实例对象。在前面的文章中,我们分析了 Context
组件,它的默认实现是 StandardContext
,它与 Manager
是一对一的关系,Manager
创建、销毁会话时,需要借助 StandardContext
获取 HttpSessionListener
列表并进行事件通知,而 StandardContext
的后台线程会对 Manager
进行过期 Session 的清理工作
org.apache.catalina.Manager
接口的主要方法如下所示,它提供了 Context
、org.apache.catalina.SessionIdGenerator
的 getter/setter 接口,以及创建、添加、移除、查找、遍历 Session
的 API 接口,此外还提供了 Session
持久化的接口(load/unload) 用于加载/卸载会话信息,当然持久化要看不同的实现类
public interface Manager {public Context getContext();public void setContext(Context context);public SessionIdGenerator getSessionIdGenerator();public void setSessionIdGenerator(SessionIdGenerator sessionIdGenerator);public void add(Session session);public void addPropertyChangeListener(PropertyChangeListener listener);public void changeSessionId(Session session);public void changeSessionId(Session session, String newId);public Session createEmptySession();public Session createSession(String sessionId);public Session findSession(String id) throws IOException;public Session[] findSessions();public void remove(Session session);public void remove(Session session, boolean update);public void removePropertyChangeListener(PropertyChangeListener listener);public void unload() throws IOException;public void backgroundProcess();public boolean willAttributeDistribute(String name, Object value);
tomcat8.5 提供了 4 种实现,默认使用 StandardManager
,tomcat 还提供了集群会话的解决方案,但是在实际项目中很少运用,关于 Manager
的详细配置信息请参考 tomcat 官方文档
- StandardManager:Manager 默认实现,在内存中管理 session,宕机将导致 session 丢失;但是当调用 Lifecycle 的 start/stop 接口时,将采用 jdk 序列化保存 Session 信息,因此当 tomcat 发现某个应用的文件有变更进行 reload 操作时,这种情况下不会丢失 Session 信息
- DeltaManager:增量 Session 管理器,用于Tomcat集群的会话管理器,某个节点变更 Session 信息都会同步到集群中的所有节点,这样可以保证 Session 信息的实时性,但是这样会带来较大的网络开销
- BackupManager:用于 Tomcat 集群的会话管理器,与DeltaManager不同的是,某个节点变更 Session 信息的改变只会同步给集群中的另一个 backup 节点
- PersistentManager:当会话长时间空闲时,将会把 Session 信息写入磁盘,从而限制内存中的活动会话数量;此外,它还支持容错,会定期将内存中的 Session 信息备份到磁盘
Session 相关的类图如下所示,StandardSession
同时实现了 javax.servlet.http.HttpSession
、org.apache.catalina.Session
接口,并且对外提供的是 StandardSessionFacade
外观类,保证了 StandardSession
的安全,避免开发人员调用其内部方法进行不当操作。而 org.apache.catalina.connector.Request
实现了 javax.servlet.http.HttpServletRequest
接口,它持有 StandardSession
的引用,对外也是暴露 RequestFacade
外观类。而 StandardManager
内部维护了其创建的 StandardSession
,是一对多的关系,并且持有 StandardContext
的引用,而 StandardContext
内部注册了 webapp 所有的 HttpSessionListener
实例。
创建Session
我们以 HttpServletRequest#getSession()
作为切入点,对 Session 的创建过程进行分析
public class SessionExample extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException {HttpSession session = request.getSession();// other code......}
整个流程图如下图所示(查看原图):
tomcat 创建 session 的流程如上图所示,我们的应用程序拿到的 HttpServletRequest
是 org.apache.catalina.connector.RequestFacade
(除非某些 Filter 进行了特殊处理),它是 org.apache.catalina.connector.Request
的门面模式。首先,会判断 Request
对象中是否存在 Session
,如果存在并且未失效则直接返回,因为在 tomcat 中 Request
对象是被重复利用的,只会替换部分组件,所以会进行这步判断。此时,如果不存在 Session
,则尝试根据 requestedSessionId
查找 Session
,而该 requestedSessionId
会在 HTTP Connector 中进行赋值(如果存在的话),如果存在 Session
的话则直接返回,如果不存在的话,则创建新的 Session
,并且把 sessionId
添加到 Cookie
中,后续的请求便会携带该 Cookie
,这样便可以根据 Cookie
中的sessionId
找到原来创建的 Session
了
在上面的过程中,Session
的查找、创建都是由 Manager
完成的,下面我们分析下 StandardManager
创建 Session
的具体逻辑。首先,我们来看下 StandardManager
的类图,它也是个 Lifecycle
组件,并且 ManagerBase
实现了主要的逻辑。
整个创建 Session
的过程比较简单,就是实例化 StandardSession
对象并设置其基本属性,以及生成唯一的 sessionId
,其次就是记录创建时间,关键代码如下所示:
public Session createSession(String sessionId) {// 限制 session 数量,默认不做限制,maxActiveSessions = -1if ((maxActiveSessions >= 0) &&(getActiveSessions() >= maxActiveSessions)) {rejectedSessions++;throw new TooManyActiveSessionsException(sm.getString("managerBase.createSession.ise"), maxActiveSessions);}// 创建 StandardSession 实例,子类可以重写该方法Session session = createEmptySession();// 设置属性,包括创建时间,最大失效时间session.setNew(true);session.setValid(true);session.setCreationTime(System.currentTimeMillis());// 设置最大不活跃时间(单位s),如果超过这个时间,仍然没有请求的话该Session将会失效session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60);String id = sessionId;if (id == null) {id = generateSessionId();}session.setId(id);sessionCounter++; // 这个地方不是线程安全的,可能当时开发人员认为计数器不要求那么准确// 将创建时间添加到LinkedList中,并且把最先添加的时间移除,主要还是方便清理过期sessionSessionTiming timing = new SessionTiming(session.getCreationTime(), 0);synchronized (sessionCreationTiming) {sessionCreationTiming.add(timing);sessionCreationTiming.poll();}return (session);
在 tomcat 中是可以限制 session 数量的,如果需要限制,请指定 Manager
的 maxActiveSessions
参数,默认不做限制,不建议进行设置,但是如果存在恶意攻击,每次请求不携带 Cookie
就有可能会频繁创建 Session
,导致 Session
对象爆满最终出现 OOM。另外 sessionId
采用随机算法生成,并且每次生成都会判断当前是否已经存在该 id,从而避免 sessionId
重复。而 StandardManager
是使用 ConcurrentHashMap
存储 session 对象的,sessionId
作为 key,org.apache.catalina.Session
作为 value。此外,值得注意的是 StandardManager
创建的是 tomcat 的 org.apache.catalina.session.StandardSession
,同时他也实现了 servlet 的 HttpSession
,但是为了安全起见,tomcat 并不会把这个 StandardSession
直接交给应用程序,因此需要调用 org.apache.catalina.Session#getSession()
获取 HttpSession
。
我们再来看看 StandardSession
的内部结构
- attributes:使用 ConcurrentHashMap 解决多线程读写的并发问题
- creationTime:Session 的创建时间
- expiring:用于标识 Session 是否过期
- lastAccessedTime:上一次访问的时间,用于计算 Session 的过期时间
- maxInactiveInterval:Session 的最大存活时间,如果超过这个时间没有请求,Session 就会被清理、
- listeners:这是 tomcat 的 SessionListener,并不是 servlet 的 HttpSessionListener
- facade:HttpSession 的外观模式,应用程序拿到的是该对象
相关文章:

Tomcat源码分析-Session源码解析
tomcat session 设计分析 tomcat session 组件图如下所示,其中 Context 对应一个 webapp 应用,每个 webapp 有多个 HttpSessionListener, 并且每个应用的 session 是独立管理的,而 session 的创建、销毁由 Manager 组件完成&…...

常见数据模型
目录 1.1两类数据模型 1.2概念模型 1.3数据模型的组成要素 1.4常见数据模型 层次模型 网状模型 关系模型 数据模型是对现实世界数据特征的抽象,也就是说数据模型是用来描述数据、组织数据和对数据进行操作的。数据模型是数据库系统的核心和基础。 1.1两类数…...

Lesson 8.3 ID3、C4.5 决策树的建模流程 Lesson 8.4 CART 回归树的建模流程与 sklearn 参数详解
文章目录一、ID3 决策树的基本建模流程二、C4.5 决策树的基本建模流程1. 信息值(information value)2. C4.5 的连续变量处理方法三、CART 回归树的基本建模流程1. 数据准备2. 生成备选规则3. 挑选规则4. 进行多轮迭代5. 回归树的预测过程四、CART 回归树…...

阿里云手机短信登录
阿里云短信服务介绍阿里云短信服务(Short Message Service)是广大企业客户快速触达手机用户所优选使用的通信能力。调用API或用群发助手,即可发送验证码、通知类和营销类短信;国内验证短信秒级触达,到达率最高可达99%&…...

Android Camera SDK NDK NDK_vendor介绍
Android Camera JNI NDK NDK_vendor介绍前言主要有哪几种interface?Android SDKCamera API 1Camera API 2小结Android NDKNDK InterfaceNDK Vendor Interface小结Camera VTS Testcase总结Reference前言 本篇博客是想介绍Android camera从application layer到camera…...

SQL基础语句小结
🍎道阻且长,行则将至。🍓 目录 一、SQL概述 1.简介 2.格式语法 3.SQL分类 二、DDL操作数据库 1.创建数据库 2.查询与使用 3.删除数据库 三、DDL:操作表 (1)数据类型 (2)创建表 (3)查询当前数据库的表 (4)删除表 (5)修改表 四、DML…...

管理类书籍推荐
管理类书籍对于每一位想要获得管理能力提升或者实现职业生涯更上一层楼的企业管理者或领导者而言,都是不可或缺的一项重要学习工具。作为管理工作从事者的职场必需品,一本出色的管理类书籍可以为我们提供大量宝贵的经验与专业建议,从而让管理…...

win10 mingw 调用python
ubuntu调用pythonhttps://blog.csdn.net/qq_39942341/article/details/129333969 我这里mingw是用msys2的 opencv也是msys2装的 安装msys2和opencv可以参考这个https://blog.csdn.net/qq_39942341/article/details/129380197?spm1001.2014.3001.5502 环境变量里加入python路…...

教你使用三种方式写一个最基本的spark程序
当需要处理大规模数据并且需要进行复杂的数据处理时,通常会使用Hadoop生态系统中的Hive和Spark来完成任务。在下面的例子中,我将说明如何使用Spark编写一个程序来处理Hive中的数据,以满足某个特定需求。假设我们有一个Hive表,其中…...

软件设计师错题集
软件设计师错题集一、计算机组成与体系结构1.1 浮点数1.2 Flynn分类法1.3 指令流水线1.4 层次化存储体系1.4.1 程序的局限性1.5 Cache1.6 输入输出技术1.7 总线系统1.8 CRC循环冗余校验码二、数据结构与算法基础2.1 队列与栈2.2 树与二叉树的特殊性2.3 最优二叉树(哈…...

【华为机试真题详解 Python实现】静态扫描最优成本【2023 Q1 | 100分】
文章目录前言题目描述输入描述输出描述示例 1输入:输出:示例 2输入:输出:题目解析参考代码前言 《华为机试真题详解》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试,期间有想了解的…...

算法刷题总结 (四) 动态规划
算法总结4 动态规划一、动态规划1.1、基础问题11.1.1、509. 斐波那契数列1.1.2、70. 爬楼梯1.1.3、746. 使用最小花费爬楼梯1.2、基础问题21.2.1、62. 不同路径1.2.2、63. 不同路径Ⅱ1.2.3、343. 整数拆分1.2.4、96. 不同的二叉搜索树1.3、背包问题1.3.1、01背包1.3.1.1、单次选…...

Grafana 转换数据的工具介绍
转换数据 Grafana 可以在数据显示到面板前对数据进行处理 1、点击Transform选项卡 2、选择要使用的转换类型,不同的转换类型配置不同 3、要新增转换类型,点击Add transformation 4、使用右上角调式按钮可以调式转换 支持的转换类型: Add f…...

Linux 学习笔记
一、 概述 1. 操作系统 ① 计算机由硬件和软件组成 ② 操作系统属于软件范畴,主要作用是协助用户调度硬件工作,充当用户和计算机硬件之间的桥梁 ③ 常见的操作系统 🤠 PC端:Windows、Linux、MacOS🤠 移动端&#…...

HTML注入专精整理
目录 HTML注入介绍 抽象解释 HTML注入的影响 HTML注入与XSS的区别 HTML元素流程图...

看完这篇我不信你不会二叉树的层序遍历【C语言】
目录 实现思路 代码实现 之前介绍了二叉树的前、中、后序三种遍历,采用的是递归的方式。今天我们来学习另外一种遍历方式——层序遍历。层序遍历不容小觑,虽然实现方法并不难,但是它所采取的思路是很值得学习的,与前三者不同&am…...

案例17-环境混用带来的影响
目录一、背景介绍背景事故二、思路&方案三、过程四、总结nginx做转发fastdfs(文件上传下载)五、升华一、背景介绍 本篇博客主要介绍开发中项目使用依赖项环境闭一只带来的恶劣影响,在错误中成长进步。 背景 本公司另外一个产品开发God…...

知识蒸馏论文阅读:DKD算法笔记
标题:Decoupled Knowledge Distillation 会议:CVPR2022 论文地址:https://ieeexplore.ieee.org/document/9879819/ 官方代码:https://github.com/megvii-research/mdistiller 作者单位:旷视科技、早稻田大学、清华大学…...

Sentinel架构篇 - 熔断降级
熔断降级 概念 除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用其它模块,可能是一个远程服务、数据库、或者第三方 API 等。然而,被依赖的服务的稳定性是不能保证的。如果依赖的服…...

shell脚本的一些记录 与jenkins的介绍
shell 脚本的执行 sh ***.sh shell脚本里面的命令 其实就是终端执行一些命令 shell 连接服务器 可以直接ssh连接 但是这样最好是无密码的 不然后面的命令就不好写了 换而言之有密码得 不好写脚本 需要下载一些expect的插件之类的才可以 判断语句 的示例 需要注意的是…...

JVM的了解与学习
一:jvm是什么 jvm是java虚拟机java Virtual Machine的缩写 jdk包含jre和java DevelopmentTools 二:什么是java虚拟机 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。java虚拟机有自己完善的硬体结构,如处理器、堆栈、寄存器等,还有…...

提升数字品牌的5个技巧
“品牌”或“品牌推广”的概念通常用于营销。因为建立您的企业品牌对于产品来说极其重要,品牌代表了您与客户互动的身份和声音。今天,让我们来看看在数字领域提升品牌的一些有用的技巧。如何在数字领域提升您的品牌?在了解这些技巧之前&#…...

java通过反射获取加了某个注解的所有的类
有时候我们会碰到这样的情况:有n个场景,每个场景都有自己的逻辑,即n个处理逻辑,这时候我们就需要通过某个参数的值代表这n个场景,然后去加载每个场景不同的bean对象,即不同的类,这些类中都有一个…...

Warshall算法
🚀write in front🚀 📜所属专栏:> 算法 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我…...

vector中迭代器失效的问题及解决办法
目录 vector常用接口 vector 迭代器失效问题 vector中深浅拷贝问题 vector的数据安排以及操作方式,与array非常相似。两者的唯一差别在于空间的运用的灵活性。array 是静态空间,一旦配置了就不能改变;要换个大(或小) 一点的房子&#x…...

【蓝桥杯刷题训练营】day05
1 数的分解 拆分成3个数相加得到该数 然后采用了一种巨愚蠢的办法: int main() {int count 0;int a 2;int b 0;int c 1;int d 9;int a1, a2, a3;int c1, c2, c3;int d1, d2, d3;for (a1 0; a1 < 2; a1){for (a2 0; a2 < 2; a2){for (a3 0; a3 <…...

线程中断interrupt导致sleep产生的InterruptedException异常
强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。 Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法当线程睡眠时,它睡在某个地方,在苏醒之前不会返回到可运行状态。 当睡眠时间到期…...

ubuntu的快速安装与配置
文章目录前言一、快速安装二 、基础配置1 Sudo免密码2 ubuntu20.04 pip更新源3 安装和配置oneapi(infort/mpi/mkl) apt下载第一次下载的要建立apt源apt下载(infort/mpi/mkl)4 安装一些依赖库等5 卸载WSLpython总结前言 win11系统 ubuntu20.04 提示:以下…...

人工智能AI工具汇总(AIGC ChatGPT时代个体崛起)
NameCategoryWebsiteDescription描述《AIGC时代:超级个体的崛起》小报童https://xiaobot.net/p/SuperIndividual 介绍AIGC,ChatGPT,使用技巧与搞钱方式。Masterpiece Studio3Dhttps://masterpiecestudio.comSimplifying 3D Creation with AI…...

【rust-grpc-proxy】在k8s中,自动注入代理到pod中,再不必为grpc调试而烦恼
目录前言原理sidecarwebhook实现安装k8s设置webhook使用尾语前言 rust-grpc-proxy 目前功能基本完善。是时候上环境开始应用了。 之前考虑是gateway模式或者sidecar模式。 思考良久之后,觉得两种模式都有使用场景,那就都支持。本次就带来sidecar模式的食…...