首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Tomcat session的实现:线程安全与管理

本文所说的session是单机版本的session, 事实上在当前的互联网实践中已经不太存在这种定义了。我们主要讨论的是其安全共享的实现,只从理论上来讨论,不必太过在意实用性问题。

1:session 的意义简说

大概就是一个会话的的定义,客户端有cookie记录,服务端session定义。用于确定你就是你的一个东西。

每个用户在一定范围内共享某个session信息,以实现登录状态,操作的鉴权保持等。

我们将会借助tomcat的实现,剖析session管理的一些实现原理。

2. tomcat 中 session 什么时候创建?

session 信息会在两个地方调用,一是每次请求进来时,框架会尝试去加载原有对应的session信息(不会新建)。二是应用自己调用getSession()时,此时如果不存在session信息,则创建一个新的session对象,代表应用后续会使用此功能。即框架不会自动支持session相关功能,只是在你需要的时候进行辅助操作。

在tomcat中,HttpServletRequest的实际类都是 RequestFacade, 所以获取session信息也是以其为入口进行。

从上面我们可以看到,session的流程大概是这样的:

1. 先查找是否有session信息存在,如果有则判断是否失效;

2. 如果不存在session或已失效,则使用一个新的sessionId(非必须)创建一个session实例;

3. session创建成功,则将sessionId写入到cookie信息中,以便客户端后续使用;

4. 每次请求完session,必定刷新下访问时间以续期;

session的管理主要有两种实现方式,类图如下:

我们先主要以基于内存的实现来理解下session的管理过程。实际上StandardManager基本就依托于 ManagerBase 就实现了Session管理功能,下面我们来看一下其创建session如何?

有兴趣的同学可以看一下sessionId的生成算法:主要保证两点:1. 随机性;2.不可重复性;

创建好session后,需要进行随时的维护:我们看下tomcat是如何刷新访问时间的?可能比预想的简单,其仅是更新一个访问时间字段,再无其他。

最后,还需要看下 HttpSession 是如何被包装返回的?

再最后,要说明的是,整个sessions的管理使用一个 ConcurrentHashMap 来存放全局会话信息,sessionId->session实例。

3. 过期session清理?

会话不可能不过期,不过期的也不叫会话了。

会话过期的触发时机主要有三个:1. 每次进行会话调用时,会主动有效性isValid()验证,此时如果发现过期可以主动清理:2. 后台定时任务触发清理;3. 启动或停止应用的时候清理;(这对于非内存式的存储会更有用些)

接下来我们看下具体如何清理过期的会话?实际应该就是一个remove的事。

清理工作的核心任务没猜错,还是进行remove对应的session, 但作为框架必然会设置很多的扩展点,为各监听器接入的机会。这些点的设计,直接关系到整个功能的好坏了。

4. session如何保证线程安全?

实际是废话,前面已经明显看出,其使用一个 ConcurrentHashMap 作为session的管理容器,而ConcurrentHashMap本身就是线程安全的,自然也就保证了线程安全了。

不过需要注意的是,上面的线程安全是指的不同客户端间的数据是互不影响的。然而对于同一个客户端的重复请求,以上实现并未处理,即可能会生成一次session,也可能生成n次session,不过实际影响不大,因为客户端的状态与服务端的状态都是一致的。

5. 使用持久化方案的session管理实现

默认情况使用内存作为session管理工具,一是方便,二是速度相当快。但是最大的缺点是,其无法实现持久化,即可能停机后信息就丢失了(虽然上面有在停机时做了持久化操作,但仍然是不可靠的)。

所以就有了与之相对的存储方案了:Persistent,它有一个基类 PersistentManagerBase 继承了 ManagerBase,做了些特别的实现:

可以看到, PersistentManager 的实现还是有点复杂的,主要是在安全性和性能之间的平衡,它和 StandardManager 基本是一种包含关系,即除了要维护内存session外,还要维护外部存储的状态。

而现实情况是,既然已经需要自行维护外部状态了,为何还要去使用tomcat自带的session管理呢?而如果站在框架session管理的设计者的角度,这可能也是无可奈何的事。

而在我们自己的session管理实现中,一般的思路还是相通的,创建 -> 查找 -> 维持 -> 删除 。 可以基于数据库,缓存,或者其他,而且相信也不是件难事。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20210315A0F6WG00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券