重写servlet API实现分布式session共享

session 机制是一种服务器端的机制,服务器使用一种散列表或者类似的结构来保存信息。在使用分布式 session 前会有这样两个疑问:

1)为什么采用分布式 session :

当我们的系统当中有多台服务器的时候,我们无法保证 session 在多台机器都存在,这是因为我们用户的请求不一定会被路由到同一台机器上。也就是说对应一个用户的 session 信息在服务器 A 上存在,但是在服务器 B 上不存在,因为请求被路由到了服务器 A 上,所以我们需要让集群中的多台机器共享 session信息。

2)为什么重写 session:

session 只能存储在本地 web服务器的内存当中,但无法满足 session 在多台服务器的分布式环境下,多台机器共享 session 数据的问题,所以我们需要重写,让它在分布式环境下,拥有 session 数据共享功能。

session配置方法

当程序需要为某个客户端的请求创建一个 session 的时候,服务器首先检查这个客户端的请求里是否包含了一个 session 标识,称为 session-id。

如果已经包含一个 session-id 则说明以前已经为此客户创建过 session,服务器就按照session-id 把这个 session 检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的 session 对象,但用户人为地在请求的 URL 后面附加上一个 JSESSION 的参数)。

如果客户请求不包含 session-id,则为此客户创建一个 session 并且生成一个与此 session 相关联的 session-id,这个session-id将在本次响应中返回给客户端保存。

其实分布式 session 并不是一个特别难的课题,实现的思路也有很多种。今天我将介绍一种使用起来非常简单的方法,只要做如下配置即可使用:

1 )导入一个 jar 在 pom 文件中

2) 在 web.xml 文件中配置一个 filter

session 使用方法

分布式 session 的使用:从使用者的角度不需要知道是否为分布式 session,一句即可搞定,而且和容器无关。

为了保证读者可以理解这种方法,下面我将以最简洁的方法来实现。

1、拦截器的实现

这个拦截器拦截了所有路径的客户端请求,并且在请求进去 Controller 之前把HttpServletRequest 替换成我自己实现的一个 HttpServletRequest,叫做DistributionSessionRequestWrapper

2、DistributionSessionRequestWrapper 的实现

HttpServletRequestWrapper 是 HttpServletRequest 的装饰类,通过继承它,覆盖你希望改变的方法,你可以改变当前 HttpServletRequest 对象的状态。

从 session 的使用角度上来说,你只会用 getSession() 这个方法,那么我覆盖这个方法就ok了,在 getSession() 中我做了两件事:

new 了一个的 HttpSession 实现叫做 DistributionSessionImpl

在 cookie 当中写入一个叫 pcxSessionId 的 cookie 进去,实际上就和 tomcat 的 jessionid 一样,这个就是用来从分布式缓存中寻找对应 session 数据的 key。

3、DistributionSessionImpl 的实现

在 DistributionSessionImpl 中有两个属性比较重要

sessionMap:用来存储一次请求中的 session 数据

sessionStore:把用户的 session 数据存储到分布式缓存的类

getId() 方法:通过这个方法可以获取用户的 cookie 中 key=“pcxSessionId”的value 值

getAttribute():通过key中 pcxSessionId从缓存中获取用户的 session 数据

setAttribute():如果为空的话,那么从分布式缓存中获取用户的 session 数据,当然如果这个用户是第一次访问的话,这个 sessionMap 可能还是为空,这个逻辑的话在sessionStore 有判断;把key-value数据存储到本地的sessionMap中,然后把数据推送到分布式缓存中

removeAttribute():清除本地 map 中的 Attribute 然后再把分布式缓存中的getID() 给删掉

Invalidate():先清除本地的 sessionmap 然后删除分布式缓存中的 session 数据,最后清除 cookie

4、SessionStore 的实现

session 存储的时候使用 hession 的序列化,然后通过调用 jedis的 api 存放session 数据。这个类应该是很容易理解的,当然具体你用 redis 还是 memcached 这个随意了。

至此,一个基本的分布式 session 就实现了。它的本质是加一个拦截器然后把 HttpServletRequest 替换成自己定义了,然后覆盖掉 getSession 方法,最后用一个我自己定义的 HttpSession 实现来完成各种操作。

总结

上述代码只是保留了最基本的实现,我们也可以继续优化封装,添加更多的功能。下面笔者以减少用户与分布式缓存机器的通信次数的优化为例,供大家参考。

从 DistributionSessionImpl 中我们可以看出,每次 setAttribute 和removeAttribute 数据都会同步到分布式缓存,这个实际上是没有必要的,虽说分布式缓存和我们的 server 虽然是在内网中通信,但是来回的次数会增加其时间损耗。

我们不能保证把一个用户的请求一直路由到同一台机器上,但是能够保证一次 request 在一台机器上,我们可以在用户的一次请求结束后把这个用户的 Session 数据同步到分布式缓存当中,以减少了与分布式缓存机器的通信次数。

本文作者:彭晨雪(点融黑帮),现就职于点融网技术部 lb 团队,java 开发工程师一枚。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容