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。很重量级,这里不表。