SNA方案之session store调研SNA方案中,session的存放是一个重要方面。javaeye中提出的解决方案主要基于memc
SNA方案之session store调研
SNA方案中,session的存放是一个重要方面。javaeye中提出的解决方案主要基于memcached:
?
codeutil通过hack tomcat6的session manage相关类将标准的servlet session存储在memcached中。该hack解决了一部分问题,但是最终没有完全绕过ManagerBase中的sessions实例和StandardSession中的attributes实例。从代码上看,群集环境中,存在着各个JVM中的sessions实例和attributes实例无法与memcached保持同步的问题,继而隐藏着session dirty或者expire机制失效的BUG。
?
另外一种方案是自定义Map<String,Map<String,Serializable>>来取代servlet容器的SessionStore机制。使用memcached作为underlying store的,仍然需要解决session expire的问题。关于memcached管理session expire的问题,balaschen等hack了memcached的代码。每次get操作的时候更新expire值,继而试图让memcached自行管理。这种方案限于每个session只能作为一个key/value pair存放于memcached。而通常更有效的存储结构是:
sessionkey:["attr1","attr2","access_timestamp"]
sessionkey_attr1:{}
sessionkey_attr2:{}
?
ROR社区使用cookie_store,很好。虽然没有看过其实现机制,但是以java的实现该是这样:
new ObjectOutputStream(new GZIPOutputStream(new CipherInputStream(new Base64OutputStream(out),cipher))).writeObject(state);
?
我个人感觉cookie item 4k的容量,存放压缩过的信息已经足够了。关于session中应该/不应该存放什么的讨论,javaeye有很多。我个人总结是,session中存放用户与服务端资源交互产生的、无法由服务端自行决定存放的状态信息。
?
?
如果仍然需要session_store的话,我还是更倾向于自定义session结构这种方案。虽然丧失了一部分容器session 机制的好处(比如event,标准接口),但是可以免去hack的痛苦,且与容器无关,轻量级。使用dbcached(memcached+nmdb+qdbm)来作为underlying store,增加了持久、故障转移等功能。
?
但是,session iterate仍然是待解决的问题。
?
为什么需要iterate?可以更加灵活的进行expire,还有在线人数统计这类常见的需求。
?
虽然qdbm提供的java client中Villa可以按照key的前缀进行iterate,但是client无法使用nmdb独占打开的那个db,而nmdb又没有提供java client,更沮丧的是其client规范中规定的可操作方法并没有iterate。目前正在调研其他解决方案。
?
?
还有基于terracotta的JVM-level clustering来管理session。很重量级,这里不表。
?
to neptune:
关于实现部分,还没仔细的想,而且我现在只是想先实现CookieStoreProvider。
至于MemcachedStoreProvider,
>>sessionId_attr_names=属性名列表(attr1,attr2)
这个我觉得不妥,试想有属性名就是"attr_names"。再者,sessionId这个key对应的value存放啥?不如就存放属性名列表。
>>sessionId_last_accessed_time=最后访问时间
由于使用mysql memory table,所以最后访问时间就不存储到memcached了。
容忍偏差是个好想法,但是现在我没有想好具体怎么使用。
>>每隔一段时间从db中得到所有的sessionId,在一个一个的得到期..
不建议,使用where access_at<current-expire即可
关于使用自定义结构的Session,如何模拟session的大部分操作和Store的交互,细节问题很多还没考虑。不过最重要的是要解决线程安全的问题。
7 楼 tangchao 2008-06-07 我的解决方案:
1、MemcachedServer 使用类似 RIAD的 0+1 方案
2、定义属性Session_ID为KEY,然后所有的Session属性和最后访问时间为值。
3、取Session_ID 的值,取他的超时时间。决定是否超时,对于session的值,不需要超时时间的。如果超时,直接remove
4、定义一个最外围的Filter,Filter开始的时候从MemcacheServer中取出Session_ID 的值,然后根据Key Gets Session的内容;然后将取得的内容付给Session对象。
5、定义一个属性更新的Listener
6、Filter执行完毕后,根据Listener收集的属性变更,然后对update 、remove的操作维护 Memcache Values,replace Session_ID 的值
7、根据需要,定义个保存Session_ID的桶,定期检查桶的内容是否过期;因为 如果没有参数 —M,Memcache采取的是 LRU算法;所定期检查的时间可以稍长,可以根据状态报告的内容来做,毕竟 过期的内容如果不访问和删除,一直保存在Memcache 中 8 楼 Arden 2008-09-05 我觉得用timesten比较合适,但是类似于这样内存数据库保存session的话,就是expired的问题比较麻烦,这个需要自己另外写个线程来维护session的过期问题。 9 楼 Arden 2008-09-05 另外一个如果自己定义session结构,完全放弃容器的session结构,这样的话对于一些开发框架会不会有影响,因为毕竟很多框架象jboss seam的状态机制都是基于标准的http session来管理的,如果是自定义的这时候就麻烦了。 10 楼 阳光晒晒 2008-11-04 Arden 写道另外一个如果自己定义session结构,完全放弃容器的session结构,这样的话对于一些开发框架会不会有影响,因为毕竟很多框架象jboss seam的状态机制都是基于标准的http session来管理的,如果是自定义的这时候就麻烦了。
接口实现...
或继承后改造
我想性能问题在没有提出前不是问题 11 楼 mycybyb 2008-11-04 session id和最后访问时间放到cookie中。
以session id为key,在memcached中存放session的属性。
定义一个filter,然后把request包装一下。所有的处理都在自己包装的request中。
1:判断是否存在session id及是否过期。
2:如果session有效,则从memcached读取session属性,并包装一个session出来。 12 楼 kabbesy 2008-11-05 mycybyb 写道session id和最后访问时间放到cookie中。
以session id为key,在memcached中存放session的属性。
定义一个filter,然后把request包装一下。所有的处理都在自己包装的request中。
1:判断是否存在session id及是否过期。
2:如果session有效,则从memcached读取session属性,并包装一个session出来。
这种应该是SNA最好的解决方案。
基础数据压缩放在cookie中(userid,last_location,last_access,somekey),透明装载session bind data