每天学习一点点之 Tomcat 是如何清除过期 Session 的

今天使用一种很临时的方案解决 Session 泄漏的问题:缩短 Session 的过期时间。这种方法虽然简单,但却非常有效。然而,这引发了一个问题:我们应该将过期时间设置为多短呢?在 Spring Boot 中,最短的过期时间是 60 秒。如果你配置的值小于 60 秒,系统会将其默认设置为 60 秒。这是由 org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getSessionTimeoutInMinutes 方法决定的:

	private long getSessionTimeoutInMinutes() {Duration sessionTimeout = getSession().getTimeout();if (isZeroOrLess(sessionTimeout)) {return 0;}return Math.max(sessionTimeout.toMinutes(), 1);}

这时候组内有同学说,过短的过期时间是否会影响服务的性能,例如,是否需要更频繁地删除 Session

为了解答这个问题,我们需要理解 “Tomcat 是如何清除 Session 的”,以及 “Tomcat 中 Session 的更新机制是否会受到 Session 过期时间设置的长短的影响”。

其实根据经验,结合 Redis 删除过期 Key,以及 ThreadLocal 清除过期 entry 等存在类似场景的框架,过期清除机制无非就是两种策略,以及一些细微的处理差异:

  • 惰性删除:只在数据被访问时才检查和删除过期的数据
    • 每次只检查当前数据
    • 顺带检查周边数据
  • 定期删除:后台定时进行扫描
    • 全量扫描
    • 随机扫描

我相信 Tomcat 的处理方式也不会脱离这两种策略。带着这个思考,那么接下来就源码分析一下 Tomcat 到底是如何清除过期 Session 的。

关于 Session,Tomcat 提供了一个常用的函数 org.apache.catalina.session.StandardSession#isValid,用于判断 Session 是否有效。如果 Session 已经无效,该函数会调用 org.apache.catalina.session.StandardSession#expire(boolean) 使 Session 过期(移除)。这表明 Tomcat 对 Session 的处理采用了惰性删除机制。

Tomcat 提供了几种不同的 Session 持久化策略,主要通过实现不同的 ManagerStore 来实现:

  1. 内存持久化:这是 Tomcat 的默认策略,由 StandardManager 实现。所有的 Session 都保存在内存中。当 Tomcat 重启或者出现故障时,所有的 Session 信息都会丢失。
  2. 文件持久化:由 PersistentManagerFileStore 实现。不活跃的 Session 会被保存到文件系统中,从而释放内存。当 Session 再次变得活跃时,可以从文件系统中恢复。
  3. 数据库持久化:由 PersistentManagerJDBCStore 实现。不活跃的 Session 会被保存到数据库中。这种策略适合于需要在多个 Tomcat 实例之间共享 Session 的情况。
  4. 分布式 Session:在一个 Tomcat 集群中,可以通过实现 ClusterableSessionDeltaManagerBackupManager 来实现 Session 的复制或者备份,从而实现 Session 的分布式管理。

本文关注的是内存持久化策略,即 StandardManager。它有一个函数 org.apache.catalina.session.ManagerBase#processExpires,该函数遍历所有的 Session,对每个 Session 判断是否过期。如果发现 Session 已失效,就会让 Session 过期:

    public void processExpires() {long timeNow = System.currentTimeMillis();Session sessions[] = findSessions();int expireHere = 0;if (log.isDebugEnabled()) {log.debug("Start expire sessions " + getName() + " at " + timeNow + " sessioncount " + sessions.length);}for (Session session : sessions) {if (session != null && !session.isValid()) {expireHere++;}}long timeEnd = System.currentTimeMillis();if (log.isDebugEnabled()) {log.debug("End expire sessions " + getName() + " processingTime " + (timeEnd - timeNow) +" expired sessions: " + expireHere);}processingTime += (timeEnd - timeNow);}

既然怀疑这个函数可能存在定时调度,其实有一个小技巧,在这个函数上打一个断点,看是否可能触发,果然没一会就触发了:

在这里插入图片描述

根据 stack trace,这个函数是由 ContainerBackgroundProcessor 执行的。

在这里插入图片描述

Tomcat 启动时会执行 threadStart 方法,该方法基于 java.util.concurrent.ScheduledExecutorService 启动一个定时任务,backgroundProcessorDelay 参数可以控制启动后多久开始执行,backgroundProcessorDelay 控制多久执行一次。

    /*** Start the background thread that will periodically check for session timeouts.*/protected void threadStart() {if (backgroundProcessorDelay > 0 &&(getState().isAvailable() || LifecycleState.STARTING_PREP.equals(getState())) &&(backgroundProcessorFuture == null || backgroundProcessorFuture.isDone())) {if (backgroundProcessorFuture != null && backgroundProcessorFuture.isDone()) {// There was an error executing the scheduled task, get it and log ittry {backgroundProcessorFuture.get();} catch (InterruptedException | ExecutionException e) {log.error(sm.getString("containerBase.backgroundProcess.error"), e);}}backgroundProcessorFuture = Container.getService(this).getServer().getUtilityExecutor().scheduleWithFixedDelay(new ContainerBackgroundProcessor(), c,backgroundProcessorDelay, TimeUnit.SECONDS);}}

这表明 Tomcat 对 Session 的处理也有定期删除机制。

总结

在 Tomcat 中,Session 的管理采用了惰性删除和定期删除两种策略:

  • 惰性删除是通过 org.apache.catalina.session.StandardSession#isValid 方法实现的,每次在判断 Session 是否有效的时候,如果 Session 已经无效,就会让 Session 过期(移除)
  • 在内存持久化策略中在内存持久化策略中,定期删除是通过 org.apache.catalina.session.ManagerBase#processExpires 方法实现的,该方法会定期遍历所有的 Session,对每个 Session 判断是否过期,如果发现 Session 已失效,就会让 Session 过期

在 Tomcat 中,Session 的更新机制并不会直接受到 Session 过期时间设置的长短的影响,但是,如果 Session 的数量过多,可能导致 Session 清理操作的效率降低。因为在每次 Session 清理操作时,都需要遍历所有的 Session,检查每个 Session 是否过期,如果过期就将其移除。如果 Session 的数量过多,那么这个过程就会消耗更多的时间和资源。

因此,虽然 Session 的过期时间设置不会直接影响 Session 的更新机制,但是 Session 的数量过多确实会对 Session 的更新效率和系统性能产生影响。为了保持系统的高效运行,应该尽量控制 Session 的数量,避免 Session 的数量过多。

欢迎关注公众号:
在这里插入图片描述

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

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

相关文章

实在智能携“TARS大模型”入选“2023中国数据智能产业AI大模型先锋企业”

近日,由数据猿与上海大数据联盟联合主办的“2023企业数智化转型升级发展论坛”在上海圆满收官。 论坛颁奖典礼上,《2023中国数据智能产业AI大模型先锋企业》等六大榜单正式揭晓,旨在表彰在AI领域为数智化升级取得卓越成就和突出贡献的企业&am…

解决“使用 CNKI 保存时发生错误。改为尝试用 DOI 保存。”【Bug Killed】

文章目录 简介解决办法跟新本地Zotero中茉莉花插件的非官方维护中文翻译器更新网页插件Zetero Connector中的Transtors 结语参考资料 简介 使用Chrome ➕ Zotero Connector保存中国知网(CNKI)的参考文献到本地的Zotero时无法正常保存,出现使…

Altium Designer学习笔记8

创建原理图元件: 画出原理图: 根据规则书画出原理图: 根据规则书画出封装图: 参照: 确认下过孔的内径和外径的最小允许值。

Vatee万腾的数字时代探险:vatee科技力量的未来洞悉

在数字化的时代潮流中,Vatee万腾以其强大的科技力量,正在进行一场前所未有的数字时代探险。 Vatee万腾的数字时代探险源于其对未来的洞悉。通过深度研究和前瞻性思考,他们将科技力量与未来趋势相结合,勾勒出数字时代的新蓝图&…

露营管理系统预约小程序效果如何

旅游经济已经复苏,并且市场规模增速加快,近一年来远途/周边游客户增多,不少旅游景区在节假日常常面对客流爆满现象。同时露营作为近几年突然火热的项目,其需求也是日渐上升。 然而在高需求的同时,我们也看到露营经营痛…

【数组栈】实现

目录 栈的概念及其结构 栈的实现 数组栈 链式栈 栈的常见接口实现 主函数Test.c 头文件&函数声明Stack.h 头文件 函数声明 函数实现Stack.c 初始化SLInit 扩容Createcapacity 压栈STPush 出栈STPop 栈顶元素STTop 判断栈是否为空STempty 栈内元素个数STSzi…

使用sqlserver备份还原,复制迁移数据库

文章目录 前言一、备份数据库二、还原数据库三、其他 前言 当初学sqlserver复制数据库的时候,老师只教了右键数据库生成sql脚本,没说数据库非常大的时候咋搞啊,分离数据库复制一份后在附加上去太危险了 百度一下备份还原数据库针对小白的资料…

财报解读:电商GMV增长30%后,快手将坚守本地生活?

快手逐渐讲好了其高质量成长的故事。 根据财报,快手三季度业绩超出预期,其中,营收279.5亿元,同比增长20.8%;调整后净利润31.7亿元,同比扭亏为盈。 而联系市场环境来看,三季度广告、电商市场较…

超详细的pytest玩转HTML报告:修改、汉化和优化

前言 Pytest框架可以使用两种测试报告,其中一种就是使用pytest-html插件生成的测试报告,但是报告中有一些信息没有什么用途或者显示的不太好看,还有一些我们想要在报告中展示的信息却没有,最近又有人问我pytest-html生成的报告&a…

6-使用nacos作为注册中心

本文讲解项目中集成nacos,并将nacos作为注册中心使用的过程。本文不涉及nacos的原理。 1、项目简介 以一个演示项目为例,项目包含三个服务,调用及依赖如下图: 由图中可以看出,coupon-customer-serv为服务的消费者&a…

基于element自动表格

需求是根据JSON文件生成表格,包含配置和自动props属性以及过滤器; 数据示例: 表格设置: /*** 表格表头信息* chineseToPinYin: 这是封装的根据中文汉字转换为拼音的方法* prop: 表头字段名* filter: 数据过滤器* label: 表头显示…

类初始化,类加载,类加载器

类初始化,类加载,类加载器 1. 类加载1.1. 类的加载1.2. 类的链接1.2.1. 验证1.2.2. 准备1.2.3. 解析 2. 类加载器2.1. 类加载器分为四种:前三种为虚拟机自带的加载器。2.2. 类加载有三种方式:2.3. **JVM类加载机制**2.4. 双亲委派…

GeoTrust通配符证书:保护您的网站安全

GeoTrust通配符 SSL证书是一种特殊的 SSL 证书类型,它可以同时为您的主域名及其所有子域提供安全保护。无论您有多少个不同的子域需要保障,都可以通过单一的 GeoTrust 通配符 SSL 证书轻松实现,极大地简化了管理流程并降低了成本。 此外&…

1688商品详情数据接口(1688.item_get)

1688商品详情数据接口是一种程序化的接口,通过这个接口,商家或开发者可以使用自己的编程技能,对1688平台上的商品信息进行查询、获取和更新。这个接口允许商家根据自身的需求,获取商品的详细信息,例如价格、库存、描述…

群晖NAS搭建WebDav服务做文件共享,可随时随地远程访问

文章目录 1. 在群晖套件中心安装WebDav Server套件1.1 安装完成后,启动webdav服务,并勾选HTTP复选框 2. 局域网测试WebDav服务2.1 下载RaiDrive客户端2.2 打开RaiDrive,设置界面语言可以选择中文2.3 点击添加按钮,新建虚拟驱动区2…

从事软件测试8年,对业务测试人员的一些思考

自从事测试工作八年多以来,经历过三个部门多条业务线,也经历过测试转型再回到测试,在此过程中对测试工作和角色的认知也逐步有些思考,想把这些思考分享给大家,希望为业务测试同学提供一些有价值的思路。 同时&#xff…

YOLOV7主干改进,使用fasternet轻量化改进主干(完整教程)

1,Pconv(来自Fasternet)(可作为模型中的基础卷积模块使用) 论文链接:https://arxiv.org/abs/2303.03667 2,为了大家方便的使用,这里我对原本的PConv的代码做了部分的改动&#xff0…

豪华程度堪比飞机头等舱?奔驰在北美发布Tourrider系列巴士

今年三月,奔驰工厂附近出现了一台特殊的测试车。其突出的前保险杠以及竖置双风挡等特殊配置,都在暗示着它并非是为欧洲市场打造。 根据特征推测,这台车应该是为北美市场打造。 就在昨天,奔驰发布了旗下全新Tourrider系列豪华客车&…

嵌入式单片机方向和Linux驱动开发方向哪个发展前景好?

嵌入式单片机方向和Linux驱动开发方向哪个发展前景好? 在某些平台上看到很多人鼓吹嵌入式Linux开发比单片机开发要好,让所有人都去做嵌入式Linux开发。说这种话的人大多数是嵌入式Linux的培训机构,或者是一开始就以嵌入式Linux入门的那一批人…

飞书如何接入ChatGPT-打造个人智能问答助手实现无障碍交流

目录 前言 环境列表 1.飞书设置 2.克隆feishu-chatgpt项目 3.配置config.yaml文件 4.运行feishu-chatgpt项目 5.安装cpolar内网穿透 6.固定公网地址 7.机器人权限配置 8.创建版本 9.创建测试企业 10. 机器人测试 总结 前言 在飞书中创建chatGPT机器人并且对话&am…