`
eyesmore
  • 浏览: 364501 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

memcached-session-0.9.jar

阅读更多

 

一、需求背景

一般的 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 自己删除。

 

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
<!-- [if !supportAnnotations]-->
<!-- [endif]--><!-- [if !supportAnnotations]--> <!-- [endif]-->

 <!-- [if !supportAnnotations]-->[lw1] <!-- [endif]--> Memcached-session-0.9.jar 中的组件,并在 init-param 中配置该组件的初始化参数

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
<!-- [if !supportAnnotations]-->
<!-- [endif]--><!-- [if !supportAnnotations]--> <!-- [endif]-->

 <!-- [if !supportAnnotations]-->[lw2] <!-- [endif]--> memcachedSession sessionid 也是基于 cookie 的,且 sessionid 的生成规则是 UUID

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
<!-- [if !supportAnnotations]-->
<!-- [endif]--><!-- [if !supportAnnotations]--> <!-- [endif]-->

 <!-- [if !supportAnnotations]-->[lw3] <!-- [endif]--> 指定服务端 sessionid 失效时间,其中 >0 表示在指定时间(秒)后失效; =0 表示永远不失效; <0 默认 30 分钟后失效。

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
<!-- [if !supportAnnotations]-->
<!-- [endif]--><!-- [if !supportAnnotations]--> <!-- [endif]-->

 <!-- [if !supportAnnotations]-->[lw4] <!-- [endif]--> 指定对哪些 url 请求的自有 HttpSession MemcachedSession 替换掉。

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
<!-- [if !supportAnnotations]-->
<!-- [endif]--><!-- [if !supportAnnotations]--> <!-- [endif]-->

 <!-- [if !supportAnnotations]-->[lw5] <!-- [endif]--> 获取的 Session 实现实例实际是 com.umpay.session.MemcachedSession ,采用的是装饰器模式给偷梁换柱了。

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
<!-- [if !supportAnnotations]-->
<!-- [endif]--><!-- [if !supportAnnotations]--> <!-- [endif]-->

 <!-- [if !supportAnnotations]-->[lw6] <!-- [endif]--> 用户自己定义的 MemcachedSession 对应的 uuid

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
<!-- [if !supportAnnotations]-->
<!-- [endif]--><!-- [if !supportAnnotations]--> <!-- [endif]-->

 <!-- [if !supportAnnotations]-->[lw7] <!-- [endif]--> Servlet 容器自有的 SessionID

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
<!-- [if !supportAnnotations]-->
<!-- [endif]--><!-- [if !supportAnnotations]--> <!-- [endif]-->

 <!-- [if !supportAnnotations]-->[lw8] <!-- [endif]--> 浏览器在再次访问同一域下的 URL 时,主动把先前下发的 uuid cookie 信息包裹在请求报文中,以便服务端依据该 ID 匹配 MemcachedSession 对象。

<!-- [if !supportAnnotations]-->
<!-- [endif]-->
分享到:
评论
1 楼 jelver 2009-07-10  
thank you very much ,i really apprecitate your help

相关推荐

Global site tag (gtag.js) - Google Analytics