1.OSCache
OSCache是一个使用较多的高性能J2EE缓存框架,适用于任何JAVA应用程序的普通缓存解决方案。可以不受限制的缓存部分jsp页面或http请求;支持永久缓存,将缓存内存随意写入硬盘;支持集群-集群缓存数据,而不需要修改代码;控制缓存对象过期时间,可插入式刷新策略;
oscache-2.1.jar;commons-logging-api-1.1.jar;log4j-1.2.11.jar
配置OSCache环境
CacheFilter只对http 200的页面请求做处理,不对其他状态做缓存处理
web.xml
<!—osCacheFilter --> <filter> <filter-name>osCacheFilter</filter-name> <filter-class> com.opensymphony.oscache.web.filter.CacheFilter </filter-class> <init-param> <param-name>time</param-name> <param-value>60</param-value> </init-param> <init-param> <param-name>scope</param-name> <param-value>session</param-value> </init-param> </filter> <filter-mapping> <filter-name>osCacheFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
oscache.properties
#缓存到内存,如果设置成false cache.memory=true #不使用无限硬盘空间 cache.unlimited.disk=false #缓存持久化实现类,磁盘持久化监听器 cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.HashDiskPersistenceListener #缓存磁盘路径,以后注意观察该目录生成的内容 cache.path=D://OSCache//cache #选择一种缓存算法,还可选 FIFOCache、UnlimitedCache cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCacheache.base.algorithm.LRUCache #cache.cluster为集群相关设置信息 #cache.cluster.multicast.ip为广播IP地址 #cache.cluster.properties为集群属性
目前新版本的OSCache已经支持集群分布式
实现分布式环境消息同事,目前比较流行的2中做法:1.JavaGroups[http://www.jgroups.org/];2.JMS 这2种底层都实现了广播通信。
采用javaGroup,我们可以看下官方文档,使用下面的方式配置
#cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JavaGroupsBroadcastingListener #cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;/ mcast_send_buf_size=150000;mcast_recv_buf_size=80000):/ PING(timeout=2000;num_initial_members=3):/ MERGE2(min_interval=5000;max_interval=10000):/ FD_SOCK:VERIFY_SUSPECT(timeout=1500):/ pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800;max_xmit_size=8192):/ UNICAST(timeout=300,600,1200,2400):/ pbcast.STABLE(desired_avg_gossip=20000):/ FRAG(frag_size=8096;down_thread=false;up_thread=false):/ pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true) #cache.cluster.multicast.ip=231.12.21.132
拷贝oscache.tld到WEB-INF下
//index.jsp,用来刷新指定页面缓存
<cache:flush key="newsinfo1" scope="session"></cache:flush>
//newinfo.jsp 页面缓存内容
<cache:cache key="newsinfo1" duration="120s" scope="application"> <br><%=new Date() %><br> </cache:cache>
cache标签(其他属性使用可以在官方文档上查阅或者http://praguesky.blog.163.com/blog/static/232970042007415731504/)
这是OSCache提供的标签库中最重要的一个标签,包括在标签中的内容将应用缓存机制进行处理,处理的方式将取决于编程者对cache标签属性的设置。
第一次请求到达时,标签中的内容被处理并且缓存起来,当下一个请求到达时,缓存系统会检查这部分内容的缓存是否已经失效,主要是以下几项:
(1)缓存时间超过了cache标签设置的time或者duration属性规定的超时时间
(2)cron属性规定的时间比缓存信息的开始时间更晚
(3)标签中缓存的内容在缓存后又被重新刷新过
(4)其他缓存超期设定
如果符合上面四项中的任何一项,被缓存的内容视为已经失效,这时被缓存的内容将被重新处理并且返回处理过后的信息,如果被缓存的内容没有失效,那么返回给用户的将是缓存中的信息。
cache标签的常用属性说明:
key
标识缓存内容的关键词。在指定的作用范围内必须是唯一的。默认的key是被访问页面的URI和后面的请求字符串。可以在同一个页面中使用很多cache标签而不指定他的key属性,这种情况下系统使用该页面的URI和后面的请求字符串,另外再自动给这些key增加一个索引值来区分这些缓存内容。但是不推荐采用这样的方式。
scope
缓存发生作用的范围,可以是application或者session。默认为application。
time
缓存内容的时间段,单位是秒,默认是3600秒,也就是一个小时,如果设定一个负值,那么这部分被缓存的内容将永远不过期。
duration
指定缓存内容失效的时间,是相对time的另一个选择,可以使用简单日期格式或者符合USO-8601的日期格式。如:duration='PT5M' duration='5s'等。
cron
指定缓存内容失效表达式,见“Cron表达式基本语法”。
refresh
false 或者true。如果refresh属性设置为true,不管其他的属性是否符合条件,这部分被缓存的内容都将被更新,这给编程者一种选择,决定什么时候必须刷新。
mode
如果不希望被缓存的内容增加到给用户的响应中,可以设置mode属性为"silent"。此时被缓存的部分不在页面上显示,而其它任意的mode属性值都会将缓存的部分显示到页面上。
groups
指定当前cache标签所属的组,可使用“,”分割组名。这样就可以对缓存项进行分组了。如果缓存项依赖于应用的其它部分或其它数据,分组就有了用武之地——当这种依赖改变时(刷新相关的组),这个组的所有缓存项都将过期。
language
使用ISO-639定义的语言码来发布不同的缓存内容(under an otherwise identical key)。要在一个多语言网站上同一段JSP代码不同用户的参数提供不同的语言时,这个属性会很有用。
refreshpolicyclass
指定自定义的刷新策略类的全限定类名。这个类继承自com.opensymphony.oscache.web.WebEntryRefreshPolicy
refreshpolicyparam
指定任意需要传给refreshpolicyclass的参数。如果没有指定refreshpolicyclass,则这个值不起作用。
这些属性可以单独使用,也可以根据需要组合使用。
2.Velocity
http://news.cnblogs.com/n/100285/
3.Varnish+ESI
varnish安装
wget http://repo.varnish-cache.org/source/varnish-2.1.5.tar.gz
tar xzvf varnish-2.1.5.tar.gz
./configure -prefix=/usr/local/varnish
make
make install
如果提示缺少 'libpcre'
yum -y install automake autoconf libtool ncurses-devel libxslt groff pcre-devel pkgconfig
varnish自己并没有提供服务,只是一个缓存服务器(Squid???)
Varnish的默认配置文件在/usr/local/varnish/etc/varnish/default.vcl(这个配置文件指示所使用的后端服务器)
backend default { .host = "127.0.0.1"; .port = "8080"; }
./sbin/varnishd -a 0.0.0.0:80 -f /usr/local/varnish/ect/varnish/default.vcl -s malloc,500M
sub vcl_recv{ #... #做一些处理,如req.request="GET"的时候用lookup查找缓存 #... return (lookup); } sub vcl_fetch{ if(req.url == "/welcome.jsp"){ return (pass); } if(req.url == "/esi.jsp"){ esi; } }
//welcome.jsp
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <%=new Date() %>
//esi.jsp
<esi:include src="/oscache_test/welcome.jsp" mce_src="oscache_test/welcome.jsp"/> <br/> <esi:include src="http://10.20.150.211:8989/oscache_test/welcome.jsp" mce_src="http://10.20.150.211:8989/oscache_test/welcome.jsp" /> <br/> <esi:include src="http://10.19.6.22:8080/oscache_test/welcome.jsp" mce_src="http://10.19.6.22:8080/oscache_test/welcome.jsp" />
对于<esi:include src="http://192.168.0.100:8080/oscache_test/welcome.jsp"/>在这种情况varnish会做esi解析,但没有缓存下来
varnish将所有的object存于一个单独的大文件中,在工作进程初始化时候这个文件就会被加载到内存中。varnish在内存中的实现和“文件系统”有点相似,具有分配、释放、修剪、合并等功能;这种设计避免了软件与系统对内存控制的冲突;像squid、oscache会将每个object存在一个小文件,相对来说,varnish的大文件可以减少文件系统频繁的操作,这就需要记录每个object在内存的偏移量,定期检查释放内存,编程难度增加,却可以提高性能。
ps -aux|grep "varnish"
我们可以看到varnish启动或有2个进程 master(management)进程和child(worker)进程。master读入存储配置命令,进行初始化,然后fork,监控child。child则分配线程进行cache工作,child还会做管理线程和生成很多worker线程。
child进程主线程初始化过程中,将存储大文件整个加载到内存中,如果该文件超出系统的虚拟内存,则会减少原来配置mmap大小,然后继续加载,这时候创建并初始化空闲存储结构体,放在存储管理的struct中,等待分配。
接着,varnish某个负责接口新http连接的线程开始等待用户,如果有新的http连接,但是这个线程只负责接收,然后唤醒等待线程池中的work线程,进行请求处理。
worker线程读入uri后,将会查找已有的object,命中直接返回,没有命中,则会从后端服务器中取出来,放到缓存中。如果缓存已满,会根据LRU算法,释放旧的object。
对于释放缓存,有一个超时线程会检测缓存中所有object的生命周期,如果缓存过期(ttl),则删除,释放相应的存储内存。
存储结构体(定义在varnish/bin/varnishd/strorage_file.c)
struct smf_sc{ const char *filename;/* 缓存大文件的名称 */ int fd; /*缓存大文件的文件描述符*/ unsigned pagesize;/*内存的页面大小,从系统调用getpagesize()获得 */ uintmax_t filesize;/*缓存大文件的大小*/ struct smfhead order;/*内存地址排序的smf尾队列头部*/ struct smfhead free[NBUCKET];/*空闲的smf尾队列头部,NBUCKET表明的是空闲页面数,大于NBUCKET-1空闲页面的smf,都挂在free[NBUCKET-1]这个尾队列上*/ struct smfhead used;/*正在被使用的smf*/ MTX mtx;/*define MTX pthread_mutex_t*/ };
基本结构体,缓存文件中一小块连续的内存,用来分配相应大小的http object(定义在strorage_file.c)
struct smf{ unsigned magic;/*魔法数字,用来检验结构体是否有效*/ #define SMF_MAGIC 0X0927a8a0 struct storage s;/*上层逻辑存储结构体*/ struct smf_sc *sc;/*smf管理存储结构体*/ int alloc;/*是否分配完成*/ off_t size;/*smf大小*/ off_t offset;/*已经分配过的内存偏移*/ unsigned char *ptr;/*指向可分配内存的起始地址*/ VTAILQ_ENTRY(smf) order;/*按内存地址排序的smf入口*/ VTAILQ_ENTRY(smf) status;/**/ struct smfhead *flist;/*指向smf_sc中free[n]相应的空闲尾队列头部*/ };