memcached session
一、需求背景
一般的 servlet 容器(如 tomcat, resin 等)实现的 javax.servlet.http.HttpSession 的可见性都仅局限于一个 web 应用程序内,即使运行在同一个 JVM 里两个不同的 web 应用之间也不可共享 session 信息。通常情况下,我们可以考虑把会话状态信息保存在数据库中或者构建一个分布式 session 服务。 Memcached-session-0.9.jar (命名为 0.9 的原因是没有经过全面测试,但基本够用)是利用memcached 作为 session 服务器构建的一个分布式可共享 sesssion 解决方案。 Memcached-session 中的信息能够被多个共享顶级域名的 web 应用所共享(注:由于 memcached-session 的 sessionid 也是借助于 cookie 的,为防止 cookie 跨域的问题,必须要求各个 web 应用在相同的顶级域名下。 对于,要跨顶级域名的多个 web 应用程序共享 session 的问题,需要解决 cookie 跨域的问题,通常的做法是通过重定向的方式让 sessionid 在第三方的一个域上生成,详细情况可参考《 SSO(UserID 方式 )SP 与 SSO 之间的通信接口 V0.1.doc 》设计文档)。
二、使用步骤
( 1 )安装 memcached 服务端并启动在默认端口 11211 ,可以选择 windows 或 linux 版本
注:所有的会话信息都以 SessionID 到 SessionObject (本身也是个类似 Map 的数据结构)键值对形式保存在 memcached 服务器端,各个 web 应用程序再通过 memcached 客户端来访问。这一点跟信息保存在数据库服务器上,各应用程序再通过 SQL 客户端来访问是一个道理。
( 2 )获取 memcached-session-0.9.jar 包,将该包及其依赖的 java_memcached_release_1.5.jar 和 commons-logging-1.0.4.jar 导入 WEB-INF/lib 目录下
注: memcached-session-0.9.jar 依赖于 java_memcached_release_1.5.jar ( memcached 服务器的 java 客户端)和commons-logging-1.0.4.jar ( apache 的日志组件)
( 3 )编辑 memcached.properties 配置文件,以保证 memcached 客户端能够正确地访问 memcached 服务端。
注: memcached-session-0.9.jar 是依据 classpath 去寻找 memcached.properties 配置文件的,所以必须保证memcached.properties 配置文件在 classpath 的根路径下,而且名称必须是 memcached.properties 。
样例
servers=127.0.0.1:11211,10.10.41.186:11211 (多个服务器之间用“ , ”隔开)
init-connection = 10
min-connection = 5
max-connection = 20
maint-sleep-millis = 30
active-check = true
failover = true
nagle = false
( 4 )在 web.xml 中配置 MemcachedFilter ,以替换 sevlet 容器自有的 HttpSession 实现。
<filter>
<display-name>MemcachedFilter</display-name>
<filter-name>MemcachedFilter</filter-name>
<filter-class>com.umpay.session.MemcachedFilter <!-- [if !supportAnnotations]-->[lw1] <!-- [endif]--> </filter-class>
<init-param>
<param-name>uuidCookieName <!-- [if !supportAnnotations]-->[lw2] <!-- [endif]--> </param-name>
<param-value>uuid</param-value>
</init-param>
<init-param>
<param-name>uuidCookieDomain</param-name>
<param-value></param-value>
</init-param>
<init-param>
<param-name>uuidCookiePath</param-name>
<param-value>/</param-value>
</init-param>
<init-param>
<param-name>uuidCookieMaxAge <!-- [if !supportAnnotations]-->[lw3] <!-- [endif]--> </param-name>
<param-value>-1</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MemcachedFilter</filter-name>
<url-pattern>/* <!-- [if !supportAnnotations]-->[lw4] <!-- [endif]--> </url-pattern>
</filter-mapping>
( 5 )透明地使用 MemcachedSession
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int c = 1;
String count = (String)request.getSession() . <!-- [if !supportAnnotations]-->[lw5] <!-- [endif]--> getAttribute( FLAG );
if (count != null ) {
c = Integer.parseInt (count)+1;
}
request.getSession().setAttribute( FLAG , c+ "" );
request.getSession().setAttribute( "LastIP" , request.getRemoteAddr());
PrintWriter writer = response.getWriter();
request.getSession().setMaxInactiveInterval(8);
writer.write( "MaxInactiveInterval = " + request.getSession().getMaxInactiveInterval()+ " second" );writer.println();
writer.write( "you accessed this page at time " + c);writer.println();
writer.write( "SESSIONID = " + request.getSession().getId());writer.println();
writer.println();
Enumeration<String> attrs = request.getSession().getAttributeNames();
while (attrs.hasMoreElements()) {
String key = attrs.nextElement();
writer.write( "AttrEnum ->" +key+ "=" +request.getSession().getAttribute(key));
writer.println();
}
writer.println();
writer.write( "CreationTime = " + new Date(request.getSession().getCreationTime()));
writer.println();
writer.write( "LastAccessedTime = " + new Date(request.getSession().getLastAccessedTime()));
writer.println();
}
三、报文分析
( 1 )初次访问时
请求报文:
(Request-Line) GET /MemSession/counter HTTP/1.1
Host localhost:8080
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language zh-cn,zh;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset gb2312,utf-8;q=0.7,*;q=0.7
Keep-Alive 300
Connection keep-alive
Cache-Control max-age=0
响应报文:
(Status-Line) HTTP/1.1 200 OK
Server Apache-Coyote/1.1
Set-Cookie uuid=532b 3c 0b-c78e-4c2f-81fa-295ab9a57acf; Domain=""; Path=/ <!-- [if !supportAnnotations]-->[lw6] <!-- [endif]-->
Set-Cookie JSESSIONID=2560E054058B509381421BB017D 8A 418; Path=/MemSession <!-- [if !supportAnnotations]-->[lw7] <!-- [endif]-->
Content-Length 272
Date Fri, 19 Jun 2009 05:22:02 GMT
(响应包体内容)
MaxInactiveInterval = 8 second
you accessed this page at time 1
SESSIONID = 532b3c0b-c78e-4c2f-81fa-295ab9a57acf
AttrEnum ->LastIP=127.0.0.1
AttrEnum ->SessionCounter=1
CreationTime = Fri Jun 19 13:22:11 CST 2009
LastAccessedTime = Fri Jun 19 13:22:14 CST 2009
( 2 )再次访问时
请求报文:
(Request-Line) GET /MemSession/counter HTTP/1.1
Host localhost:8080
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language zh-cn,zh;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset gb2312,utf-8;q=0.7,*;q=0.7
Keep-Alive 300
Connection keep-alive
Cookie JSESSIONID=2560E054058B509381421BB017D8A418; uuid=532b 3c 0b-c78e-4c2f-81fa-295ab9a57acf <!-- [if !supportAnnotations]-->[lw8] <!-- [endif]-->
Cache-Control max-age=0
响应报文:
(Status-Line) HTTP/1.1 200 OK
Server Apache-Coyote/1.1
Content-Length 272
Date Fri, 19 Jun 2009 05:22:11 GMT
(响应包体内容)
MaxInactiveInterval = 8 second
you accessed this page at time 2
SESSIONID = 532b3c0b-c78e-4c2f-81fa-295ab9a57acf
AttrEnum ->LastIP=127.0.0.1
AttrEnum ->SessionCounter=2
CreationTime = Fri Jun 19 13:22:11 CST 2009
LastAccessedTime = Fri Jun 19 13:22:14 CST 2009
四、 FAQ
( 1 ) web 应用程序重启, MemcachedSession 信息会不会丢失呀?
答:不会, MemcachedSession 信息是保存在 Memcached 服务端的,各个 web 应用只是通过 memcached-session-0.9.jar 去访问 Memcached 服务端。只有 Memcached 服务端重启时,信息才会丢失。
( 2 )服务端 MemcachedSession 的过期时间如何设置?
答:在 web.xml 的 com.umpay.session.MemcachedFilter 的 initParam 初始化配置时通过
<init-param>
<param-name>uuidCookieMaxAge</param-name>
<param-value>-1</param-value>
</init-param>
可以配置,该配置对所有客户端生效;
也可以对某个浏览器专门使用 request.getSession().setMaxInactiveInterval(8); 来设置特定的超时时间。在实现机制上, memcached-session-0.9.jar 会在从 memcached 服务端取回数据时,依据系统当前时间 - 最后一次访问时间来判断 MemcachedSession 是否过期,如果过期,此时才删除服务端的数据。也就是说只有当数据已经过期,并且浏览器触发该数据的访问时 MemcachedSession 才会从服务端真的删除,否则只有让 memcached 自己删除。
<!-- [endif]-->
<!-- [if !supportAnnotations]-->[lw1] <!-- [endif]--> Memcached-session-0.9.jar 中的组件,并在 init-param 中配置该组件的初始化参数
<!-- [if !supportAnnotations]--><!-- [if !supportAnnotations]-->[lw2] <!-- [endif]--> memcachedSession 的 sessionid 也是基于 cookie 的,且 sessionid 的生成规则是UUID 。
<!-- [if !supportAnnotations]--><!-- [if !supportAnnotations]-->[lw3] <!-- [endif]--> 指定服务端 sessionid 失效时间,其中 >0 表示在指定时间(秒)后失效; =0 表示永远不失效; <0 默认 30 分钟后失效。
<!-- [if !supportAnnotations]--><!-- [if !supportAnnotations]-->[lw4] <!-- [endif]--> 指定对哪些 url 请求的自有 HttpSession 被 MemcachedSession 替换掉。
<!-- [if !supportAnnotations]--><!-- [if !supportAnnotations]-->[lw5] <!-- [endif]--> 获取的 Session 实现实例实际是 com.umpay.session.MemcachedSession ,采用的是装饰器模式给偷梁换柱了。
<!-- [if !supportAnnotations]--><!-- [if !supportAnnotations]-->[lw6] <!-- [endif]--> 用户自己定义的 MemcachedSession 对应的 uuid
<!-- [if !supportAnnotations]--><!-- [if !supportAnnotations]-->[lw7] <!-- [endif]--> Servlet 容器自有的 SessionID
<!-- [if !supportAnnotations]--><!-- [if !supportAnnotations]-->[lw8] <!-- [endif]--> 浏览器在再次访问同一域下的 URL 时,主动把先前下发的 uuid 的 cookie 信息包裹在请求报文中,以便服务端依据该 ID 匹配 MemcachedSession 对象。
<!-- [if !supportAnnotations]-->- MemSession.rar (419.1 KB)
- 下载次数: 55
- SSO_UserID方式_SP与SSO之间的通信接口V0.1.pdf (188.3 KB)
- 下载次数: 31
- memcached-session使用说明V0.1.pdf (304.2 KB)
- 下载次数: 47
- memcached全面剖析.pdf (929.5 KB)
- 下载次数: 49