用缓冲技术提高JSP应用的性能和稳定性之OSchche应用(3)

Oscache

特点

缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。

拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。

永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。

支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。

缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。

上一篇讲到如何配置oschche下面介绍如何应用:

1 建立一个**Bean的缓存类**Cache.

2 import com.opensymphony.oscache.general.*;import com.opensymphony.oscache.base.*;

3 建立一个**DAO类以便操作数据库(也可将上两项的内容直接合并到这里).

4 在**Cache类里生成一个GeneralCacheAdministrator的实例admin用来管理缓存.

GeneralCacheAdministrator admin = new GeneralCacheAdministrator();

5 **Cache中的方法 如.clear(),flush().基本调用的为OSCache的 Java API.

6 在**Cache添加getBeans()和getBean()方法 以便获取缓存中的实例对象.具体实现可参照上面的例子.

7 主要用到的GeneralCacheAdministrator的方法有

public Object getFromCache(String key) throws NeedsRefreshException; -- 从缓存中获取一个key标识的对象.

public Object getFromCache(String key, int refreshPeriod) throws NeedsRefreshException ; -- 从缓存中获取一个key标识的对象.  refreshPeriod刷新周期,标识此对象在缓存中保存的时间(单位:秒)

注意:

如果一个NeedsRefreshException出现 必须调用admin.putInCache或admin.cancelUpdate来避免死锁情况发生.

OSCache的使用主要有4种:

1.POJO 缓存

2.HTTP Response 缓存

3.JSP Tag Library 缓存

4.O/R Data Access 缓存

1、POJO 缓存

这种方式的缓存直接调用OSCache的API进行,主要用于处理页面内容会根据参数动态改变,可以将参数设置为key值来保存数据:

首先,声明成员变量:

// OSCache Adminitrator instance

private static GeneralCacheAdministrator cacheAdmin = null;

其次,进行初始化:

public RingArtistAction() {

cacheAdmin = new GeneralCacheAdministrator();

}

将POJO进行缓存:

// Cache data key and refresh period

String key = sex + ":" + place;

int refreshPeriod = Constants.getIntegerValue(Constants.OSCACHE_REFRESH_PERIOD).intValue();

try {

// Get from the cache

artists = (Map) cacheAdmin.getFromCache(key, refreshPeriod);

} catch (NeedsRefreshException nre) {

try {

// Get the value (probably from the database)

int count = getArtistCount(sex, place, errors);

artists = getArtistData(sex, place, count, errors);

// Store in the cache

cacheAdmin.putInCache(key, artists);

} catch (Exception ex) {

// We have the current content if we want fail-over.

artists = (Map) nre.getCacheContent();

// It is essential that cancelUpdate is called if the

// cached content is not rebuilt

cacheAdmin.cancelUpdate(key);

ex.printStackTrace();

}

}

POJO(简单Java对象)缓存。一个POJO缓存是一个系统——它担当一个"面向对象的"分布式的缓存。在这个系统中,一旦一个用户把POJO依附到该缓存上,那么缓冲方面(例如复制和持续性)应该对用户是透明的。一个用户只需简单地在该POJO上操作而不须担心更新该缓存内容或维持对象关系的问题。不存在显式的API调用可用来管理该缓存。

2、HTTP Response 缓存

这种方式的缓存用来处理整个页面的内容固定,不会根据参数动态改变:

首先在web.xml中配置CacheFilter:

<filter>

<filter-name>CacheFilter</filter-name>

<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>

<init-param>

<param-name>time</param-name>

<param-value>86400</param-value>

</init-param>

<init-param>

<param-name>scope</param-name>

<param-value>application</param-value>

</init-param>

</filter>

将所有需要缓存的页面加入filter-mapping:

<filter-mapping>

<filter-name>Set Character Encoding</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

注意,只有返回状态为200(HttpServletResponse.SC_OK)的内容才会被缓存

HTTP中缓存的目的是为了在很多情况下减少发送请求,也即直接返回缓存;同时在许多情况下可以不需要发送完整响应。前者减少了网络回路的数量,挺高响应速度,HTTP利用一个“过期(expiration)”机制来为此目的。后者减少了网络应用的带宽,HTTP用“验证(validation)”机制来为此目的。

HTTP定义了3种缓存机制:

l Freshness allows a response to be used without re-checking it on the origin server, and can be controlled by both the server and the client. For example, the Expires response header gives a date when the document becomes stale, and the Cache-Control: max-age
directive tells the cache how many seconds the response is fresh for.

l Validation can be used to check whether a cached response is still good after it becomes stale. For example, if the response has a Last-Modified header, a cache can make a conditional request using the If-Modified-Since header to see if it has changed.

l Invalidation is usually a side effect of another request that passes through the cache. For example, if URL associated with a cached response subsequently gets a POST, PUT or DELETE request, the cached response will be invalidated.

HTTP Response缓存如何工作

所有的缓存都用一套规则来帮助他们决定什么时候使用缓存中的副本提供服务(假设有副本可用的情况下);一些规则在协议中有定义(HTTP协议1.0和1.1),一些规则由缓存的管理员设置(浏览器的用户或者代理服务器的管理员);

一般说来:遵循以下基本的规则(不必担心,你不必知道所有的细节,细节将随后说明)

1.如果响应头信息:告诉缓存器不要保留缓存,缓存器就不会缓存相应内容;

2.如果请求信息是需要认证或者安全加密的,相应内容也不会被缓存;

3.如果在回应中不存在校验器(ETag或者Last-Modified头信息),缓存服务器会认为缺乏直接的更新度信息,内容将会被认为不可缓存。

4.一个缓存的副本如果含有以下信息:内容将会被认为是足够新的 ?含有完整的过期时间和寿命控制头信息,并且内容仍在保鲜期内;

?浏览器已经使用过缓存副本,并且在一个会话中已经检查过内容的新鲜度;

?缓存代理服务器近期内已经使用过缓存副本,并且内容的最后更新时间在上次使用期之前;

?够新的副本将直接从缓存中送出,而不会向源服务器发送请求;

5.如果缓存的副本已经太旧了,缓存服务器将向源服务器发出请求校验请求,用于确定是否可以继续使用当前拷贝继续服务;

总之:新鲜度和校验是确定内容是否可用的最重要途径:

如果副本足够新,从缓存中提取就立刻能用了;

而经缓存器校验后发现副本的原件没有变化,系统也会避免将副本内容从源服务器整个重新传输一遍。

3、JSP Tag 缓存

JSP Tag缓存主要用于缓存JSP页面的局部内容:

<cache:cache key="especialcategory" cron="* 5 * * *">

<jsp:include page="/ringcategory.do" flush="true" >

<jsp:param name="ringType" value="1"/>

</jsp:include>

</cache:cache>

页面缓存通常采用oscache来进行实现,oscache提供了一个jsp tag,可通过这个tag来包含需要缓存的内容部分,当然,缓存的这个内容部分需要有对服务器的请求或逻辑计算等的,可想而知,去缓存一段静态html是没有意义的。页面的缓存的使用对于系统的响应速度确实会有很大的提升,在实现页面缓存时最麻烦的主要是缓存的key的定义以及缓存更新的通知,这个自然框架是没法解决的,不过缓存更新的通知其实在框架中可以考虑一种通知模型的,就像事件通知那样。在实际的项目中,可以实现一个这样的通知模型或者就是简单的采用单例方式来标识某个key是否需要更新。

关于jsp cache的几条建议

1.jsp cache最好做在过滤器上,把需要缓冲的页面集中在同一个目录下,每次更改只须更改web.xml就可以完成缓冲设置,这样比较方便.

2.Gzip压缩可以将页面压缩得很小,平均压缩比为1/3,jsp cache的HashMap缓冲压缩后的页面,肯定比没压缩前更节约内存消耗,并且效率更高.

4、O/R Data Access 缓存

数据缓存估计大家都很熟悉,就是对系统的数据进行缓存的方式,典型的就是Hibernate的一级、二级数据缓存。

数据缓存在实现上如果是用hibernate的话更多的是直接使用hibernate的一级、二级以及查询缓存,如果要实现的话可以去参考hibernate的实现机制。

数据缓存的key在一级、二级缓存中采用的都是数据的标识键的值的方式,查询缓存采用的是查询参数、查询语句的方式。

数据缓存的更新则是hibernate在进行存储时直接更新缓存的内容,而对于查询缓存则是采用全部直接清除的方式,这样在下次进行查询时自然会重新去查询,

大家可能会想,为什么页面缓存和处理缓存不采用这样的方式来实现缓存的更新,稍微想想就知道了,在后台发生改变的时候其实是不知道需要移除哪些key的,

所以hibernate为了避免这个麻烦,采用的就是当数据一旦发生改变的时候就清除全部的查询缓存,而不是只去清除相关的缓存,

其实这里可以采用一种订阅式的模型,当然,也增加了框架的复杂度。

ORM缓存最强大的是它的透明化和灵活可配置,你可以使用Ehcache, 也可以选Jboss,还可以用Tangosol。

请阅读参考资料的内容获取详情。

参考资料:

Taking the load off: OSCache helps databases cope:http://www.theserverside.com/articles/article.tss?l=OSCacheHelpsDatabases

具体实现:

建立缓存管理类CacheManager

package com.jrgy.util;

public class CacheManager {

private BaseCache newsCache;

private static CacheManager instance;

private static Object lock = new Object();

private CacheManager() {

// 初始BaseCache;

newsCache = new BaseCache("CNYJWeb", 12000);

}

public static CacheManager getInstance() {

if (instance == null) {

synchronized (lock) {

if (instance == null) {

instance = new CacheManager();

}

}

}

return instance;

}

//删除?所有缓存对象

public void removeAllCache() {

newsCache.removeAll();

}

//删除被缓存的对象

public void delCacheByKey(String key){

newsCache.remove(key);

}

//添加被缓存的对象

public void add(String key, Object value) {

newsCache.put(key, value);

}

// 获取被缓存的对象

public Object get(String key){

try {

return newsCache.get(key);

} catch (Exception e) {

return null;

}

}

}

建立个工具类BaseController  GeneralCacheAdministrator主要对实现持久化对象的保存以及取出的相关的操作。

package com.jrgy.util;

import java.util.Date;

import com.opensymphony.oscache.base.NeedsRefreshException;

import com.opensymphony.oscache.general.GeneralCacheAdministrator;

public class BaseCache extends GeneralCacheAdministrator {

private static final long serialVersionUID = -4397192926052141162L;

private int refreshPeriod; // 过期时间(单位为秒);

private String keyPrefix; // 关键字前??字符;

public BaseCache(String keyPrefix, int refreshPeriod) {

super();

this.keyPrefix = keyPrefix;

this.refreshPeriod = refreshPeriod;

}

// 添加被缓存的对象;

public void put(String key, Object value) {

this.putInCache(this.keyPrefix + "_" + key, value);

}

// 删除被缓存的对象;

public void remove(String key) {

this.flushEntry(this.keyPrefix + "_" + key);

}

// 根据日期删除?被缓存的对对象;

public void removeAll(Date date) {

this.flushAll(date);

}

//删除?所有的缓存对象?;

public void removeAll() {

this.flushAll();

}

// 获取被缓存的对象;

public Object get(String key) throws Exception {

try {

return this.getFromCache(this.keyPrefix + "_" + key,

this.refreshPeriod);

} catch (NeedsRefreshException e) {

this.cancelUpdate(this.keyPrefix + "_" + key);

throw e;

}

}

}

使用oschache

package com.jrgy.web.controller;

import java.io.UnsupportedEncodingException;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.servlet.ModelAndView;

import com.jrgy.main.service.impl.LoadStartDataManagerImpl;

import com.jrgy.pojo.domain.DocInfo;

import com.jrgy.pojo.domain.FriendlyLink;

import com.jrgy.pojo.domain.ItemInfo;

import com.jrgy.pojo.domain.Periodical;

import com.jrgy.util.Constants;

import com.jrgy.util.ItemCodeConstants;

import com.jrgy.util.PageObject;

import com.jrgy.util.PageView;

import com.jrgy.web.service.IWebIndexManager;

@Controller

public class WebIndexController extends BaseController {

private static final long serialVersionUID = 6316819588600885728L;

@Autowired

IWebIndexManager webIndexManager;

@Autowired

LoadStartDataManagerImpl loadStartData;

@SuppressWarnings("unchecked")

@RequestMapping("/index.do")

public ModelAndView saveDept(HttpServletRequest request,

HttpServletResponse response) {

PageObject pageObject = new PageObject();

List<ItemInfo> itemList = new ArrayList<ItemInfo>();// 获取栏目

if ((itemList = (List<ItemInfo>) getCache(itemList, ItemCodeConstants.CACHE_JRGY_ITEM)).size() == 0) {

itemList = webIndexManager.addItemList(itmeCode);

addCache(ItemCodeConstants.CACHE_JRGY_ITEM, itemList);

}

}

}

因为配置在D:\CNYJWeb\cache\application生成缓存的文件夹:

结论:

    1.缓存的清空与更新,要尽量精确的去操作受到更新影响的对象,而不是全部搞掉。

   在Hibernate当中,也提供了sessionFactory.evict(class, id)这样细粒度的清空缓存对象的方法。

sessionFactory.evice(class)的操作,要看这样的操作是否频繁,如果频繁,对于缓存的作用就会大大的折扣。

   2.如果缓存对象过多,对于失效的算法与处理,要与业务对象的特性紧密的联合起来,通过事件来驱动对象的失效。

   3.对于商业对象的缓存,必须要深刻分析对象的生命周期,业务特性。

   4.对于数据不一致的风险,要有足够的认识与预防手段。

   5.合理的估计对象的大小,分配足够的内存

   6.如果只使用中心缓存,只能减小数据库的压力,对于网络带宽的压力,还是有的,速度上也远远逊于本地缓存的效果,所以要结合本地缓存+中心缓存的策略方案,即提高速度,避免群集复制时的瓶颈。

用缓冲技术提高JSP应用的性能和稳定性之OSchche应用(3)

时间: 2024-08-28 16:23:40

用缓冲技术提高JSP应用的性能和稳定性之OSchche应用(3)的相关文章

ASP.NE的缓存技术提高Web站点的性能

一:我们为什么要使用缓存? 先来理解一下asp.net缓存技术的基本原理:把访问频繁的数据以及需要花大量的时间来加载的数据缓存在内存中,那么用户在下次请求同样的数据时,直接将内存中的数据返回给用户,从而大大的提高了应用程序的性能. 二:缓存的分类(整页缓存,页面部分缓存,应用程序缓存) 那么什么时候我们要用到整页缓存,什么时候用到部分页面缓存,什么时候我们要用到应用程序缓存呢? >>整页缓存的情况: a)不需要平凡更新数据的页面 b)占用大量时间和资源的页面 >>页面部分缓存: 顾

转 高性能、高弹性JSP和Servlet性能优化

高性能.高弹性JSP和Servlet性能优化 2009-01-05 10:00 执木 网络转载 字号:T | T 本文讲述了开发高性能.高弹性的JSP页面和Servlet的性能优化技术.其意思是建立尽可能快的并能适应数量增长的用户及其请求.在本文中,你将学习已经实践和得到证实的性能调整技术,它将大大地提高你的Servlet和Jsp页面的性能,进而提升J2EE的性能. AD:WOT2015 互联网运维与开发者大会 热销抢票 你的J2EE应用是不是运行的很慢?它们能不能承受住不断上升的访问量?本文讲

Win32 GDI 非矩形区域剪裁,双缓冲技术

传统的Win32通过GDI提供图形显示的功能,包括了基本的绘图功能,如画线.方块.椭圆等等,高级功能包括了多边形和Bezier的绘制.这样app就不用关心那些图形学的细节了,有点类似于UNIX上的X-window协议.你信或者不信,那些看上去很花哨的控件,其实就是一笔一划画上去的而已.GDI提供了画笔(用于线条).画刷(用于填充).调色板(用于支持256色显示).字体(用于文字).如果简单的图形不足以表达,你可以使用位图和画布(DC,设备上下文)直接将图像绘制到屏幕上去.此外,GDI还支持一些简

干货系列1:Java互联网网站开发工程师 的技术提高与晋升路线(技术专精)

前几天写了自己对于Java软件开发工程师职业发展规划方面的一些感悟,陆续收到一些反馈,希望我能再就Java工程师不同的开发(职责)方向谈谈职业发展问题.(上一篇:Java软件开发工程师的自我修养与晋升(B/S结构)下面就具体谈谈Java程序员的另一个职责方向:Java互联网开发工程师 Java互联网开发工程师的主要岗位职责是: 负责网站平台的系统设计.数据库设计.代码开发,以及技术攻关的工作. 职业发展道路基本有3条: 第一条路线(技术专精): 初级Java开发---中级--高级---项目主管-

avalon与双缓冲技术

avalon与双缓冲技术 avalon1.5一个重要技术升级是引进异步渲染.异步渲染在游戏界有一个更专业的名字,叫双缓冲.游戏界要刷新界面与我们刷新浏览器视图,面临的问题是一致的.视图是由许多存在套嵌关系的方块组成,它们每一个的改动,都可能引起reflow(其父节点,其父父节点的大小重新计算),这是造成性能问题的关键. 双缓冲技术的主要原理是:当一个动画争先显示时,程序又在改变它,前面的画面还没显示完,程序又要求重新绘制,这样屏幕就会不停闪烁.为了避免闪烁,可以使用双缓冲技术,将要处理的图片都放

Android开发之用双缓冲技术画图

双缓冲技术主要用在绘图,动画效果上,其原理就是:将资源先加载到缓冲区,然后再将缓冲区整个加载到View上面去.双缓冲技术能够有效防止闪烁,提高显示质量. DrawView.java: package com.example.handdraw; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.C

Java知多少(101)图像缓冲技术

当图像信息量较大,采用以上直接显示的方法,可能前面一部分显示后,显示后面一部分时,由于后面一部分还未从文件读出,使显示呈斑驳现象.为了提高显示效果,许多应用程序都采用图像缓冲技术,即先把图像完整装入内存,在缓冲区中绘制图像或图形,然后将缓冲区中绘制好的图像或图形一次性输出在屏幕上.缓冲技术不仅可以解决闪烁问题,并且由于在计算机内存中创建图像,程序可以对图像进行像素级处理,完成复杂的图像变换后再显示. [例 12-6]小应用程序程序演示图像缓冲显示技术.程序运行时,当鼠标在图像区域内按下时,图像会

双缓冲技术讲解

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 首先要搞清楚计算机运行原理,计算机载运行时是将将最大的任务分解成多个任务,然后一个接一个地执行. 一个典型的例子,每个游戏引擎必须解决的问题是渲染. 当游戏画出用户看到的世界时,比如

通过分区(Partitioning)提高Spark的运行性能

在Sortable公司,很多数据处理的工作都是使用Spark完成的.在使用Spark的过程中他们发现了一个能够提高Sparkjob性能的一个技巧,也就是修改数据的分区数,本文将举个例子并详细地介绍如何做到的. 查找质数 比如我们需要从2到2000000之间寻找所有的质数.我们很自然地会想到先找到所有的非质数,剩下的所有数字就是我们要找的质数. 我们首先遍历2到2000000之间的每个数,然后找到这些数的所有小于或等于2000000的倍数,在计算的结果中可能会有许多重复的数据(比如6同时是2和3的