本来一个Tomcat集群4台服务器工作的很好,随着访问量的增加本来的粘性Session方式的配置没办法很好的一碗水端平了.Session复制的话对于网络又是一个负担,所以才自己实现了一套利用Memcache的Session实现.
网上已经有很多这样的实现了,比如修改Tomcat的Manager的http://code.google.com/p/memcached-session-manager/.
但由于我这里还有其他的Servlet容器,所以也就没有使用完全自己实现了一套,现在运行在www.etnet.com.cn网站上.
从那开始呢....其他的Servlet容器我总不能再一一去实现吧。。。。最后还是决定使用过滤器来偷梁换柱了.
先是 CacheSessionFilter ,这个过滤器负责将普通的HttpServletRequest替换成我们自己的实现.
- public class CacheSessionFilter extends BaseFilter {
- **
- * 替换原始的Request,修改为
- * com.etnetchina.servlet.wrapper.CacheSessionHttpServletReqeust。
- * 并根据是否新生成了Session来更新客户端的cookie.
- *
- * @param request 请求。
- * @param response 响应。
- * @param chain 下一个过滤器。
- * @throws java.io.IOException
- * @throws javax.servlet.ServletException
- */
- public void doFilter(
- ServletRequest request,
- ServletResponse response,
- FilterChain chain)
- throws IOException, ServletException {
- logger.debugLog("CacheSessionFilter to work.");
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- HttpServletResponse httpResponse = (HttpServletResponse) response;
- CacheSessionHttpServletReqeust cacheRequest =
- new CacheSessionHttpServletReqeust(
- httpRequest,
- httpResponse,
- filterConfig.getServletContext());
- cacheRequest.setSessionCookieName(sessionCookieName);
- cacheRequest.setMaxInactiveInterval(maxInactiveInterval);
- cacheRequest.setCookieDomain(cookieDomain);
- cacheRequest.setCookieContextPath(cookieContextPath);
- cacheRequest.setSessionAttributeListeners(sessionAttributeListeners);
- cacheRequest.setSessionListeners(sessionListeners);
- chain.doFilter(cacheRequest, httpResponse);
- CacheHttpSession cacheSession = cacheRequest.currentSession();
- if (cacheSession != null) {
- if (!cacheSession.synchronizationCache()) {
- WebUtil.failureCookie(
- httpRequest,
- httpResponse,
- sessionCookieName,
- cookieDomain,
- cookieContextPath);
- }
- }
- }
- }
这个过滤器的核心就是doFilter方法了,做了三件事.
第一是替换HttpServletRequest.
第二是如果Session失效,负责删除Cookie中的SessionId.
最后一件就是如果Session中的数据被改变了同步到缓存中.
现在重点是我们换上的CacheHttpServletRequest有什么用呢,很简单只是在应用调用getSession()方法时返回我们实现的Session.其核心的代码很简单,如下.
- private HttpSession doGetSession(boolean create) {
- if (cacheSession != null) {
- //local,return.
- logger.debugLog("Session[{0}] was existed.", cacheSession.getId());
- } else {
- Cookie cookie = WebUtil.findCookie(this, getSessionCookieName());
- if (cookie != null) {
- logger.debugLog("Find session`s id from cookie.[{0}]",
- cookie.getValue());
- cacheSession = buildCacheHttpSession(cookie.getValue(), false);
- } else {
- cacheSession = buildCacheHttpSession(create);
- }
- }
- if (cacheSession != null) {
- //dead?
- if (cacheSession.isInvalid()) {
- cacheSession.invalidate();
- cacheSession.synchronizationCache();
- cacheSession = buildCacheHttpSession(create);
- }
- if (cacheSession != null) {
- cacheSession.access();
- }
- }
- return cacheSession;
- }
getSession()和getSession(boolean)方法实际调用的就是这个方法,为了减少创建的损耗在一次请求中利保只会创建一次.最后更新一下这个Session的最后访问时间.
每一次请求结束,都会进行一次缓存同步.由于每次讲求都会造成访问时间的更新,所以这个值是一直会被put到缓存中的.
启用只需要在web.xml做如下配置.
- <filter>
- <description>修改默认的Session储存机制,改为使用某个缓存来储存。</description>
- <filter-name>CacheSessionFilter</filter-name>
- <filter-class>com.etnetchina.servlet.filter.session.CacheSessionFilter</filter-class>
- <init-param>
- <description>sessionId在Cookie中的名称</description>
- <param-name>sessionCookieName</param-name>
- <param-value>etnetsessionid</param-value>
- </init-param>
- <init-param>
- <description>Session的最大不活动时间(秒)</description>
- <param-name>maxInactiveInterval</param-name>
- <param-value>60</param-value>
- </init-param>
- </filter>
还可以有以下参数可配置
cookieDomain为存放cookie的域设置。默认为null.
cookieContextPath为存放cookie的路径。如果不设置将使用默认的contextPath.
sessionAttributeListeners 为HttpSessionAttributeListener监听器实现类全限定名,多个名称以","分隔.
sessionListeners 为HttpSessionListener监听器实现类的全限定名,多个名称以","分隔.
- <filter-mapping>
- <filter-name>CacheSessionFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
加上一个过滤器就行了.
其他分布式缓存实现方法
https://code.google.com/p/memcached-session-filter/
相关推荐
基于ZooKeeper的分布式Session实现_已发布.docx
zookeeper实现分布式session sample
基于redis实现的分布式session控制,多站点 多服务器均可兼容,使用方法:本地启动redis并配置到webconfig中
分布式服务集群下实现session共享解决方案.docx
7.分布式Session使用redis实现 8.分布式服务追踪与调用链Sleuth+ZipKin C.项目运营与部署环境 1.分布式设施环境,统一采用docker安装 2.使用jenkins+docker实现自动部署 3.微服务API管理ApiSwagger 4.使用GitLab代码...
缓存和Session:注解redis缓存数据,Spring-session和redis实现分布式session同步,重启服务会话不丢失。 数据同步:基于redis的分布式锁。 Web安全:实现XSS过滤和CSR过滤。 多系统交互:Dubbo,ActiveMQ多系统交互...
NULL 博文链接:https://jacktanlikejava.iteye.com/blog/875119
完美实现分布式集群Session共享 简单多tomcat8+redis的session共享实现,支持tomcat8、tomcat8.5、tomcat9,不能用直接联系我积分双倍返回。
利用redis实现分布式session,用Spring Session提供了集群Session功能,默认采用外置的Redis来存储Session数据,以此来解决Session共享的问题。
【ASP.NET编程知识】浅谈ASP.NET Core中间件实现分布式 Session.docx
场景应用:利用Redis实现分布式Session案例
spring session分布式session会话管理 分布式系统session的管理
session简介.doc
采用Memcached实现分布式Session所需的jar包 史上最全的
秒杀系统视频:第3章 实现用户登录以及分布式session功能
主要介绍了浅谈ASP.NET Core中间件实现分布式 Session,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
分布式中使用Redis实现Session共享(下)共4页.pdf.zip