- 浏览: 520183 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (422)
- 重要 (12)
- BUG解决备忘录 (32)
- 环境搭建 (17)
- 开源组件 (4)
- 数据库 (16)
- 设计模式 (4)
- 测试 (3)
- javascript (5)
- Android (14)
- jdk相关 (9)
- struts2 (10)
- freemark (3)
- 自定义扩展及工具类 (5)
- jdk5新特性及java基础 (13)
- ssh及其他框架 (15)
- linux (32)
- tcp-ip http协议 (8)
- 服务器集群与负载均衡 (34)
- 项目管理相关 (11)
- 实用小技术 (10)
- 架构相关 (14)
- firefox组件 (11)
- spider (6)
- 产品设计 (11)
- PHP (1)
- ws (4)
- lucene (10)
- 其他 (2)
- BI (1)
- NoSQL (3)
- gzip (1)
- ext (4)
- db (6)
- socket (1)
- 源码阅读 (2)
- NIO (2)
- 图片处理 (1)
- java 环境 (2)
- 项目管理 (4)
- 从程序员到项目经理(一):没有捷径 (1)
- bug (1)
- JAVA BASE (8)
- 技术原理 (0)
- 新框架新技术 (1)
- 量化与python (1)
- 系统编程 (0)
- C语言 (0)
- 汇编 (0)
- 算法 (0)
最新评论
-
hyspace:
别逗了,最后一个算法根本不是最优的,sort(function ...
数组去重——一道前端校招试题 -
washingtin:
楼主能把策略和路由的类代码贴出来吗
Spring + iBatis 的多库横向切分简易解决思路 -
sdyjmc:
初略看了一下,没有闹明白啊,均衡负载使用Nginx,sessi ...
J2EE集群原理 I -
shandeai520:
谢谢大神!请教大神一个问题:假如我有三台服务器,连接池的上限是 ...
集群和数据库负载均衡的研究 -
hekuilove:
给lz推荐一下apache commonsStringUtil ...
request 获取 ip
系统要集群,使用SNA方案。
一、 缓存的处理
缓存要使用统一的缓存服务器,集中式缓存。
原先的实现采用ehcache。
在spring里的配置,以资源缓存为例:
- <!-- 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 >
<!-- 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进行管理,初始化、启动、停止。
resourceCacheBackend负责实际执行缓存操作,put 、get、remove。
resourceCache实现具有业务语义的业务应用层面的缓存操作,内部调用resourceCacheBackend操作。
现在采用memcached。
关于客户端,采用文初封装的客户端,地址在http://code.google.com/p/memcache-client-forjava/
。
使用spring的FactoryBean进行二次封装。同理:
memcachedManager负责对memcached进行管理,初始化、启动、停止。
代码:
- /**
- * 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();
- }
- }
/** * 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" />
<bean id="memcachedManager" class="com.framework.extcomponent.cache.MemcachedCacheManagerFactoryBean"/>
resourceCacheBackend负责实际执行缓存操作,put 、get、remove。
代码:
- /**
- * 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);
- }
- }
/** * 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="resourceCacheBackend" class="com.framework.extcomponent.cache.MemcachedCacheFactoryBean"> <property name="cacheManager" ref="memcachedManager"/> <property name="cacheName" value="memcache"/> </bean>
resourceCache同上,替换新的实现类MemcachedBasedResourceCache即可。
二、 Session失效的处理
采用memcached作为httpsession的存储,并不直接保存httpsession对象,自定义SessionMap,SessionMap直接继承HashMap,保存SessionMap。
会话胶粘:未失败转发的情况下没必要在memcached保存的SessionMap和httpsession之间复制来复制去,眉来眼去。
利用memcached计数器保存在线人数。
系统权限采用了acegi,在acegi的拦截器链里配置snaFilter
- < 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 >
<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>
注意需要配置在第一个。
snaFilter的职责:
1、 没有HttpSession时,创建HttpSession;
2、 创建Cookie保存HttpSession id;
3、 如果Cookie保存的HttpSession id与当前HttpSession id一致,说明是正常请求;
4、 如果Cookie保存的HttpSession id与当前HttpSession id不一致,说明是失败转发;失败转发的处理:
4.1、根据Cookie保存的HttpSession id从memcached获取SessionMap;
4.2、SessionMap属性复制到当前HttpSession;
4.3、memcached删除SessionMap。
5、 判断当前请求url是否是登出url,是则删除SessionMap,在线人数减1.
代码:
- 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 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); }
利用HttpSessionAttributeListener监听httpsession的属性变化,同步到memecached中的sessionmap。
- 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 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); }
利用HttpSessionListener,sessionDestroyed事件时根据sessionid删除memcached里的sessionMap(如果存在)。不再担心httpsession的过期问题。
- 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);
- }
- }
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); } }
三、 文件保存的处理
和缓存类似,采用集中式的文件服务。对于linux,采用nfs。参考文档http://linux.vbird.org/linux_server/0330nfs.php#What_NFS_perm
。关键在于对权限的分配。
应用程序本身不用修改。
发表评论
-
图片转换成文字
2011-04-04 23:28 1111在工作中,我常常在想 ... -
网银在线支付接口和应用
2011-03-10 10:25 1174最近关注项目中在线支付,所以看一下文档,在线支付应用开发: ... -
Jcrop(图片裁剪)中文文档手册
2011-02-24 23:53 1888多彩科技原创翻译,转载请注明出处:http://www.kmw ... -
java图片裁剪原理
2011-02-24 23:16 1326总体思想: 1.前台网页用js得到裁剪图片的id及x,y ... -
js+java 带进度条的文件上传,同步+异步
2011-02-24 23:12 3294同步上传: 多个文件上传时,按顺序依次上传,后面的必须等待前 ... -
licence控制的设计
2010-12-11 00:06 12961.版权声明 本文是关于如何通过序列号来加载加密 ... -
权限 授权之 - License
2010-12-10 23:57 2256中 国是个盗版软件横 ... -
使用Jakarta-ORO库的几个例子
2010-12-06 15:07 1124简介 Jakarta-ORO是最全面以及优 ... -
深入浅出CGlib-打造无入侵的类代理
2010-12-06 00:32 775CGlib是什么? CGlib是一个强大的,高性能,高质 ...
相关推荐
Arcus 是一个基于 memcached 的云缓存,由 NAVER Corp 公司开发。 arcus-memcached 经过大幅度的修改,可以支持 NAVER 的功能和性能要求。Arcus 支持多种数据机构 (List, Set, B tree),除了支持基本的memcached ...
该插件是一款基于Memcached的分布式Session共享解决方案源码,由21个文件组成,涵盖Java源代码、XML配置、项目结构等。支持Tomcat6及以上版本,旨在实现应用服务器集群间的Session共享,提高系统在分布式环境下的...
C#使用memCached实现缓存 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。...
### Tomcat 基于 Memcached 的 Session 保持与 Nginx 反向代理实现 在分布式系统中,为了提高应用的可用性和扩展性,通常会采用多台服务器集群部署的方式来提供服务。对于 Java Web 应用而言,Tomcat 是一个常见的...
- Memcached通过将数据存储在内存中,实现了快速的数据检索,因为它避免了磁盘I/O操作。 2. **.NET 3.5中的Memcached支持**: - 在.NET环境中,我们可以使用各种库来与Memcached交互,如EnyimMemcached或...
本主题将深入探讨如何基于Java客户端对Memcached进行封装,以便更高效地在Java应用中使用它。 首先,我们需要理解Java中的Memcached客户端库,如spymemcached或xmemcached。这两个库都提供了与Memcached服务器通信...
为了实现这一目标,我们可以结合Nginx反向代理服务器和memcached内存缓存系统来达到高效、可靠的Session共享。以下是对这个主题的详细阐述: 首先,让我们理解Session的概念。Session是Web应用程序用来跟踪用户状态...
通过以上步骤,我们构建了一个基于Nginx+Tomcat+Memcached的高可用Web服务集群,实现了Session的共享,提高了系统的扩展性和稳定性。在实际运营过程中,还需要关注监控、日志、安全等方面,确保系统的健康运行。
1. `spymemcached-2.8.4.jar`:这是一个基于Java的Memcached客户端库,用于连接和操作Memcached服务器,处理session的存取操作。 2. `memcached-session-manager-1.8.3.jar`:这个库提供了session管理器,实现了将...
在J2EE session管理中,Memcached可以作为集中式的session存储,替代默认的基于cookie或本地服务器内存的session存储方式。 实现步骤如下: 1. **配置Memcached服务器**:首先,你需要安装并运行一个Memcached服务...
Memcached Go Queue, 简称mgq, 是一个用Go语言写的,基于memcached协议的消息队列。其父亲mcq是最早应用于weibo的基础消息中间件,有着高性能,解耦的优点,使得其广泛应用于微博
公司要求组织一个基于Java的memcached培训,整理了这个文档。里面有4个文件,包括memcached部署,memcached培训,监控工具memcache-top安装和daemontools安装。文档是基于word2013的,打不开的话,右键--属性--解锁
memcached实现集群的session共享问题,处理集群服务器情况下,memcached的session共享解决方案
而PHP实现的Memcached队列类则是在这一基础上进行的扩展,它允许开发者创建并管理一个基于Memcached的队列,以支持并发操作和特定的队列策略。 首先,这个类提供了多进程并发写入和读取的能力。这意味着多个PHP进程...
这个压缩包包含了基于.NET的Memcached实例源码和DLL,以及相关的PPT介绍,是学习和理解Memcached在.NET环境下的应用的宝贵资源。 首先,我们来详细了解一下Memcached的基本概念。Memcached是一个简单的键值存储系统...
`memcached-session-manager`是Java的一个库,用于在基于Tomcat的Web应用中实现基于Memcached的session共享,这在分布式环境中尤为重要。 标题中的"session共享 memcached-session-manager 1.9.6 jar"指的正是这个...
3. **修改web.xml配置**:在应用的web.xml中,配置session的管理器,使其使用memcached客户端,而不是默认的基于内存的session管理器。这通常涉及到设置session存储策略和相关参数。 4. **处理序列化与反序列化**:...
该项目为Java Web应用中的session共享设计,采用memcached作为后端存储,源码包含21个文件,涵盖10个Java类、5个XML配置文件、2个属性文件、1个Git忽略文件、1个LICENSE文件、1个Markdown文档和1个JSP页面。
Memcached的一个重要特性是其基于内存的存储方式,这使得数据读取速度非常快。 Memcached的分布式实现并不依赖于服务器之间的通信,而是依赖于客户端的算法。其中,最常用的分布式策略是“余数计算分散法”。客户端...