锁定老帖子 主题:基于memcached的SNA实现
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-10-28
系统要集群,使用SNA方案。 <!-- EhCache Manager --> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation"> <value>classpath:ehcache.xml</value> </property> </bean> <bean id="resourceCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager" ref="cacheManager"/> <property name="cacheName" value="resourceCache"/> </bean> <bean id="resourceCache" class="com.framework.extcomponent.security.authentication.services.acegi.cache.EhCacheBasedResourceCache" autowire="byName"> <property name="cache" ref="resourceCacheBackend"/> </bean>
cacheManager负责对ehcache进行管理,初始化、启动、停止。 /** * User: ronghao * Date: 2008-10-14 * Time: 10:36:30 * 管理Memcached 的CacheManager */ public class MemcachedCacheManagerFactoryBean implements FactoryBean, InitializingBean, DisposableBean { protected final Log logger = LogFactory.getLog(getClass()); private ICacheManager<IMemcachedCache> cacheManager; public Object getObject() throws Exception { return cacheManager; } public Class getObjectType() { return this.cacheManager.getClass(); } public boolean isSingleton() { return true; } public void afterPropertiesSet() throws Exception { logger.info("Initializing Memcached CacheManager"); cacheManager = CacheUtil.getCacheManager(IMemcachedCache.class, MemcachedCacheManager.class.getName()); cacheManager.start(); } public void destroy() throws Exception { logger.info("Shutting down Memcached CacheManager"); cacheManager.stop(); } }
<bean id="memcachedManager" class="com.framework.extcomponent.cache.MemcachedCacheManagerFactoryBean"/>
/** * User: ronghao * Date: 2008-10-14 * Time: 10:37:16 * 返回 MemcachedCache */ public class MemcachedCacheFactoryBean implements FactoryBean, BeanNameAware, InitializingBean { protected final Log logger = LogFactory.getLog(getClass()); private ICacheManager<IMemcachedCache> cacheManager; private String cacheName; private String beanName; private IMemcachedCache cache; public void setCacheManager(ICacheManager<IMemcachedCache> cacheManager) { this.cacheManager = cacheManager; } public void setCacheName(String cacheName) { this.cacheName = cacheName; } public Object getObject() throws Exception { return cache; } public Class getObjectType() { return this.cache.getClass(); } public boolean isSingleton() { return true; } public void setBeanName(String name) { this.beanName=name; } public void afterPropertiesSet() throws Exception { // If no cache name given, use bean name as cache name. if (this.cacheName == null) { this.cacheName = this.beanName; } cache = cacheManager.getCache(cacheName); } }
<bean id="resourceCacheBackend" class="com.framework.extcomponent.cache.MemcachedCacheFactoryBean"> <property name="cacheManager" ref="memcachedManager"/> <property name="cacheName" value="memcache"/> </bean>
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=snaFilter,httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor </value> </property> </bean>
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { final HttpServletRequest hrequest = (HttpServletRequest) servletRequest; final HttpServletResponse hresponse = (HttpServletResponse) servletResponse; String uri = hrequest.getRequestURI(); logger.debug("开始SNA拦截-----------------" + uri); HttpSession httpSession = hrequest.getSession(); String sessionId = httpSession.getId(); //如果是登出,则直接干掉sessionMap if (uri.equals(logoutUrl)) { logger.debug("remove sessionmap:" + sessionId); //在线人数减1 getCache().addOrDecr("userCount",1); getCache().remove(sessionId); } else { String cookiesessionid = getSessionIdFromCookie(hrequest, hresponse); if (!sessionId.equals(cookiesessionid)) { createCookie(sessionId, hresponse); SessionMap sessionMap = getSessionMap(cookiesessionid); if (sessionMap != null) { logger.debug("fail over--------sessionid:" + sessionId + "cookiesessionid:" + cookiesessionid); initialHttpSession(sessionMap, httpSession); cache.remove(cookiesessionid); } } } filterChain.doFilter(hrequest, hresponse); }
public void attributeAdded(HttpSessionBindingEvent event) { HttpSession httpSession = event.getSession(); String attrName = event.getName(); Object attrValue = event.getValue(); String sessionId = httpSession.getId(); logger.debug("attributeAdded sessionId:" + sessionId + "name:" + attrName + ",value:" + attrValue); SessionMap sessionMap = getSessionMap(sessionId); if (sessionMap == null){ //在线人数加1 getCache().addOrIncr("userCount",1); sessionMap = new SessionMap(); } logger.debug("name:" + attrName + ",value:" + attrValue); sessionMap.put(attrName, attrValue); getCache().put(sessionId, sessionMap); } public void attributeRemoved(HttpSessionBindingEvent event) { HttpSession httpSession = event.getSession(); String attrName = event.getName(); String sessionId = httpSession.getId(); logger.debug("attributeRemoved sessionId:" + sessionId + "name:" + attrName); SessionMap sessionMap = getSessionMap(sessionId); if (sessionMap != null) { logger.debug("remove:" + attrName); sessionMap.remove(attrName); getCache().put(sessionId, sessionMap); } } public void attributeReplaced(HttpSessionBindingEvent event) { attributeAdded(event); }
public void sessionDestroyed(HttpSessionEvent event) { HttpSession httpSession = event.getSession(); String sessionId = httpSession.getId(); logger.debug("session Removed sessionId:" + sessionId); SessionMap sessionMap = getSessionMap(sessionId); if (sessionMap != null) { logger.debug("remove sessionmap:" + sessionId); //在线人数减1 getCache().addOrDecr("userCount",1); getCache().remove(sessionId); } }
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-10-29
好文章,讲的很透彻
|
|
返回顶楼 | |
发表时间:2009-10-06
不错啊,不过可能还有问题:
比如原先的Web服务器宕机了,那Memcached 中的相关信息就无法被删除了 |
|
返回顶楼 | |
发表时间:2009-10-06
还有个问题啊,比如有两台WebServer,客户端先接入第一个Server,留下了一个Session,由于种种原因,在第一个Server还正常的情况下接入了第二个Server,过一段时间,第一个Server由于检测到该客户端Session过期,而删除了Memcached中的数据。
|
|
返回顶楼 | |
发表时间:2009-10-10
lvjinhua 写道 不错啊,不过可能还有问题:
比如原先的Web服务器宕机了,那Memcached 中的相关信息就无法被删除了 Memcache采用先进先出策略,所以不用担心。 |
|
返回顶楼 | |
发表时间:2009-10-10
lvjinhua 写道 还有个问题啊,比如有两台WebServer,客户端先接入第一个Server,留下了一个Session,由于种种原因,在第一个Server还正常的情况下接入了第二个Server,过一段时间,第一个Server由于检测到该客户端Session过期,而删除了Memcached中的数据。
接入第二个server 就会产生一个新的session吧,哈哈,首先session默认是不可序列化的。那么请看步骤四: 4、 如果Cookie保存的HttpSession id与当前HttpSession id不一致,说明是失败转发;失败转发的处理: 4.1、根据Cookie保存的HttpSession id从memcached获取SessionMap; 4.2、SessionMap属性复制到当前HttpSession; 4.3、memcached删除SessionMap。 |
|
返回顶楼 | |
发表时间:2009-10-10
建议再配置一个本地缓存,从而提高效率
|
|
返回顶楼 | |
发表时间:2009-10-10
zhangkaitao 写道 lvjinhua 写道 不错啊,不过可能还有问题:
比如原先的Web服务器宕机了,那Memcached 中的相关信息就无法被删除了 Memcache采用先进先出策略,所以不用担心。 Memcached不是FIFO,而是LRU吧。 |
|
返回顶楼 | |
发表时间:2009-10-12
dennis_zane 写道 zhangkaitao 写道 lvjinhua 写道 不错啊,不过可能还有问题:
比如原先的Web服务器宕机了,那Memcached 中的相关信息就无法被删除了 Memcache采用先进先出策略,所以不用担心。 Memcached不是FIFO,而是LRU吧。 是,呵呵。 |
|
返回顶楼 | |
浏览 8796 次