本章导读
缓存主要是为了提高数据的读取速度。因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容量数据时,使用缓存来直接为客户端服务,可以减少客户端与服务器端的数据交互,从而大大提高程序的性能。
本章从缓存所在的命名空间“System.Web.Caching”开始,详细介绍框架提供的缓存类和操作方法,主要涉及简单数据的缓存、数据缓存依赖和数据库缓存依赖三个技术要点,最后演示一个完全使用缓存实现数据读取的实例。讲解流程如图16-1所示。
图16-1 缓存命名空间的讲解流程
16.1 System.Web.Caching简介
本节从缓存命名空间的总体简介和组成结构入手,从整体上对System.Web.Caching进行概述。
16.1.1 System.Web.Caching概述
System.Web.Caching是用来管理缓存的命名空间。缓存就是将服务器端的数据暂时保存在客户端,方便用户的读取。缓存命名空间的父级空间是“System.Web”,由此可以看出,缓存通常用于Web网站的开发,包括在B/S项目中的开发。缓存的设计主要是考虑到网络带宽可能会延缓数据的提交和回发,如果将数据保存在客户端,用户可以直接从客户端读取数据,这样数据就是从本地提取的,不会再受网络的影响。
System.Web.Caching命名空间提供与缓存有关的所有操作类,具体包括哪些类将在下一节详细介绍。
16.1.2 System.Web.Caching命名空间内的类组成
缓存命名空间主要提供三种操作:缓存数据对象、对象的缓存依赖和数据库的缓存依赖。其中缓存任何对象都使用一个类Cache,但当缓存发生改变时,普通对象和数据库对象的依赖处理不同。
图16-2罗列的是在三层结构中缓存的部署情况。两个依赖类CacheDependency和SqlCache Dependency主要更改发生变化的缓存数据,起到通知的作用。当数据没有被缓存时,使用Cache类进行添加。
下面根据图16-2的部署,来介绍图中使用的缓存类。这些类的说明如表16-1所示。
图16-2 三层结构中缓存的部署图
表16-1 缓存命名空间中的类及其说明
类 名 | 说 明 |
Cache | 对缓存对象的编辑类,其操作包括缓存的增、删、改 |
CacheDependency | 基本缓存对象的依赖,当基本对象发生变化时,更新缓存内容 |
SqlCacheDependency | 数据库缓存对象的依赖,当数据库中的数据变化时,更新缓存内容 |
16.2 管理缓存的类:Cache类
Cache类用来存储数据对象,并提供方法对这些对象进行编辑。本节主要介绍Cache类包含的方法,以及如何使用这些方法实现数据对象的缓存。
16.2.1 功能说明
Cache类属于字典类,其根据一定的规则存储用户需要的数据,这些数据的类型不受限制,可以是字符串、数组、数据表、Dataset和哈希表等。
使用Cache类的优点是当缓存的数据发生变化时,Cache类会让数据失效,并实现缓存数据的重新添加,然后通知应用程序,报告缓存的及时更新。
16.2.2 语法定义
Cache类的语法定义如下:
public sealed class Cache : IEnumerable
通过其定义可以发现,Cache类是“sealed”定义的类,表示此类被密封,不能被继承。同时Cache类还继承了IEnumerable接口,表示允许对集合中的数据进行枚举操作。
缓存的生命周期随着应用程序域的活动结束而终止,也就是说只要应用程序域依然处于活动状态,缓存就会一直保持,因为每个应用程序域都会创建一个缓存实例。此实例的信息通过HttpContext对象的Cache属性或Page对象的Cache属性获取。
下面的代码演示如何将数组数据添加到缓存中:
ArrayList myarray = new ArrayList(); //创建数组数据
myarray.Add("1.学习园地");
myarray.Add("2.交流论坛");
myarray.Add("3.帮助");
Cache.Add("Category", myarray); //将数组添加到缓存中
16.2.3 方法详解
Cache类的方法主要提供对缓存数据的编辑操作,如增、删、改等。其中最常用的方法及其说明如表16-2所示。
表16-2 Cache类的主要方法及其说明
名 称 | 说 明 |
Add | 将数据添加到Cache对象 |
Insert | 向Cache中插入数据项,可用于修改已经存在的数据缓存项 |
Remove | 移除Cache对象中的缓存数据项 |
Get | 从Cache对象中获取指定的数据项,注意返回的是Object类型,需要进行类型转换 |
GetType | 从Cache对象中获取数据项的类型,判断数据类型后,方便进行转换 |
GetEnumerator | 循环访问Cache对象中的缓存数据项。注意其返回类型是“IDictionaryEnumerator” |
技巧:要想修改缓存数据,只需要重新为缓存赋值即可。
最需要注意的是Add方法,其使用语法如下:
public Object Add (
string key,
Object value,
CacheDependency dependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
CacheItemPriority priority,
CacheItemRemovedCallback onRemoveCallback
)
在使用Add方法时,以上7个参数是必需的,其代表意义如下:
— 参数“key”代表缓存数据项的键值,必须是唯一的。
— 参数“value”代表缓存数据的内容,可以是任意类型。
— 参数“dependencies”表示缓存的依赖项,也就是此项的更改意味着缓存内容已经过期。如果没有依赖项,可将此值设置为NULL。
— 参数“absoluteExpiration”是日期型数据,表示缓存过期的时间,.NET 2.0提供的缓存在过期后是可以使用的,能使用多长时间,就看这个参数的设置。
— 参数“slidingExpiration”的类型表示一段时间间隔,表示缓存参数将在多长时间以后被删除,此参数与absoluteExpiration参数相关联。
— 参数“priority”表示撤销缓存的优先值,此参数的值取自枚举变量“CacheItemPriority”,优先级低的数据项将先被删除。此参数主要用在缓存退出对象时。
— 参数“onRemoveCallback”表示缓存删除数据对象时调用的事件,一般用做通知程序。
下面的代码演示了如何应用Cache类的这些方法。在使用本代码时需要注意,代码中使用了Arraylist对象,所以需要添加对命名空间“System.Collections”的引用,同时使用Cache类别忘记了添加命名空间“System.Web.Caching”。
protected void Page_Load(object sender, EventArgs e)
{
ArrayList myarray = new ArrayList(); //创建数组数据
myarray.Add("1.学习园地");
myarray.Add("2.交流论坛");
myarray.Add("3.帮助");
//将数组添加到缓存中——使用Add方法
Cache.Add("Category", myarray, null, DateTime.Now.AddSeconds(60), TimeSpan.Zero, CacheItemPriority.Normal, null);
myarray[1] = "2.交流园地"; //修改数组数据
Cache.Insert("Category", myarray); //使用Insert方法修改缓存数据
string tmpStr = "这是一个临时数据";
Cache["tmpdata"] = tmpStr;
//使用Get方法获取缓存数据
Response.Write(Cache.Get("tmpdata").ToString()+"<br/>");/
Cache["tmpdata"] = "这是一个临时字符串"; //重新为缓存赋值的技巧
Response.Write(Cache.Get("tmpdata").ToString() + "<br/>");
//使用GetType方法判断缓存数据的类型
if (Cache["Category"].GetType().Name == "ArrayList")
Response.Write("类型是数组");
//使用GetEnumerator方法遍历缓存中的数据
IDictionaryEnumerator mycache = Cache.GetEnumerator();
while (mycache.MoveNext())
Response.Write(mycache.Value + "<br/>");
Cache.Remove("tmpdata");//使用Remove方法移除缓存的临时数据
}
技巧:在使用GetType方法时,如果要判断类型,需要使用Object.GetType().Name属性获取类型的名称。
上述代码的运行结果如下:
这是一个临时数据
这是一个临时字符串
类型是数组这是一个临时字符串
System.Collections.ArrayList
其中在读取类型为ArrayList的数据时,由于没有进行类型转换,所以取出的是类型为“System.Collections.ArrayList”的对象。本书会在本节最后的实例中介绍如何读取数组的详细内容。
16.2.4 属性详解
Cache类的属性主要用来获取缓存数据的一些基本信息,如缓存的项总数、指定位置的缓存项等。本书主要介绍两个属性:Count和Item。
Count用来获取缓存中所有的项的总数。使用方法如下:
Response.Write(Cache.Count);
Item用于返回指定项的内容,一般继承“IEnumerable”接口的类都有这样的属性,注意项需要使用“[ ]”包装。其使用方法如下:
Response.Write(Cache[“Category”].ToString());
16.2.5 典型应用:实现数据的缓存快速读取功能
Cache主要用来缓存使用频率高且不需经常更新的数据。本例实现一个目录列表的缓存。为了简便,列表的内容并没有从数据库中读取,而是保存在一个ArrayList对象中。
本例的目的是将目录列表填充到下拉框中,当缓存失效后,目录列表的内容为空。演示的步骤如下所述。
在VS2005中创建一个网站,命名为“CacheSample”。
打开默认生成的Default.aspx页,在其中添加一个下拉列表框和一个按钮。
按F7键切换到页面的代码视图。不要忘记对命名空间的引用,代码如下:
using System.Web.Caching;
using System.Collections;
在“Page_Load”事件中判断是否存在目录缓存,如果没有,则将目录添加到缓存中。详细代码如下所示,其中目录列表的保存时间是5秒。
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ArrayList myarray = new ArrayList();//假设ArrayList的内容来自数据库
myarray.Add("古代历史");
myarray.Add("当代文学");
myarray.Add("流行小说");
myarray.Add("武侠小说");
if (Cache["Categorys"] == null) //判断是否存在缓存
{
//如果缓存不存在,则添加——保存时间是5秒
Cache.Add("Categorys", myarray, null, DateTime.Now.AddSeconds(5),
TimeSpan.Zero, CacheItemPriority.Normal, null);
}
}
}
回到设计视图,双击按钮控件,切换到按钮的事件代码中。
在按钮的双击事件中,需要判断是否有目录的缓存,有则在下拉框中显示目录内容,没有则清空下拉框。详细代码如下:
protected void Button1_Click(object sender, EventArgs e)
{
if (Cache["Categorys"] != null) //判断缓存是否失效
{
//如果没有失效,则取出缓存的列表,注意类型的转换。
DropDownList1.DataSource = (ArrayList)Cache["Categorys"];
DropDownList1.DataBind();
}
else
{
DropDownList1.Items.Clear(); //如果已经失效,则清空列表
}
}
按Ctrl+S组合键保存所有的代码,再按F5键运行程序。在5秒以内如果单击按钮,则正常显示目录列表,如果超过5秒,则缓存对象已经不存在,所以下拉列表框的内容为空。
本节主要介绍了Cache类的使用方法,其中并没有涉及缓存依赖内容,即当实际数据改变时,缓存是否随着改变。下一节将通过学习“CacheDependency”类了解缓存依赖的详细实现。
16.3 缓存依赖类:CacheDependency类
CacheDependency类是架设在Cache类和实际数据之间的桥梁。本节将详细介绍如何利用CacheDependency类实现数据缓存的及时更新。
16.3.1 功能说明
CacheDependency类被称为是缓存依赖类,其具体意义表现在当缓存对象的实际数据发生改变时,它能及时通知缓存对象。例如缓存对象“Category”保存的是一个XML文件的数据,如果XML文件发生了变化,那么系统通过CacheDependency类就会及时更新缓存对象“Category”的内容,这样就能保证用户读取的永远是最新的数据。
16.3.2 语法定义
CacheDependency类的语法定义如下:
public class CacheDependency : IDisposable
其中继承了接口“IDisposable”,此接口主要用来定义释放分配的非托管资源的方法。继承此接口必须实现方法Dispose,以实现资源的释放。
CacheDependency类的构造函数实现了8个重载,下面的代码列出了这些重载的函数,并详细说明了各函数的参数。了解这些函数就可以知道CacheDependency究竟能为缓存带来什么优势。
//假设缓存的来源文件是当前目录下的data.xml文件
//缓存依赖的文件路径
CacheDependency mydep = new CacheDependency("data.xml");
//缓存依赖的文件可以有多个
CacheDependency mydep1=new CacheDependency(new string []{"data.xml","data1.xml"});
//检查缓存依赖更改的依据时间
CacheDependency mydep2 = new CacheDependency("data.xml", DateTime.Now);
//检查多个依赖文件更改的依据时间
CacheDependency mydep3 = new CacheDependency(new string[] { "data.xml", "data1.xml" }, DateTime.Now);
//检查依赖多个文件,也依赖多个缓存键值
CacheDependency mydep4 = new CacheDependency(new string[] { "data.xml", "data1.xml" },
new string[] { "Category", "Category1" });
//关联依赖,还可以依赖于另一个文件缓存依赖
CacheDependency mydep5 = new CacheDependency(new string[] { "data.xml", "data1.xml" },
new string[] { "Category", "Category1" }, mydep);
//文件和键值上次修改的依据时间
CacheDependency mydep6 = new CacheDependency(new string[] { "data.xml", "data1.xml" },
new string[] { "Category", "Category1" }, DateTime.Now);
//文件、另一个缓存依赖和键值上次修改的依据时间
CacheDependency mydep6 = new CacheDependency(new string[] { "data.xml", "data1.xml" },
new string[] { "Category", "Category1" }, mydep,DateTime.Now);
16.3.3 方法和属性
虽然CacheDependency类完成了很重要的功能,但其组成结构却比较简单,主要有两个属性和一个方法。
— 属性“HasChanged”:判断CacheDependency对象是否已更改。
— 属性“UtcLastModified”:返回上次依赖项的修改日期
— 方法“Dispose”:释放CacheDependency对象所占有的资源。因为缓存类继承了接口“IDispose”,所以必须实现此方法。
由于缓存类的构成比较简单,本节并没有给出演示代码,属性和方法的使用将在下一节的实例中演示。
注意:只有Cache类的Insert和Add方法才可以为缓存添加依赖项。
16.3.4 典型应用:用CacheDependency获取最新的数据
本例主要演示如何使用CacheDependency类实现数据的及时更新。实例中使用一个GridView控件显示XML文件的数据,当XML文件的数据发生改变时,客户端可以及时更新。其实现的功能如图16-3所示。
图16-3 用CacheDependency获取最新数据的功能实现图
演示的详细步骤如下所述。
打开VS2005,创建一个网站,命名为“CacheDependencySample”。
在网站根目录下,添加一个XML文件,用来为控件提供数据,内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<book>
<bookinfo>
<name>英国古代</name>
<price>28.00</price>
</bookinfo>
<bookinfo>
<name>中国历史</name>
<price>20.00</price>
</bookinfo>
</book>
打开默认生成的Default.aspx页,添加一个GridView控件和一个按钮控件。
按F7键切换到窗体的代码视图,在Page_Load事件中书写生成缓存的代码。详细内容如下:
private static CacheDependency mydepen;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//创建XML数据源
DataSet myds = new DataSet();
//数据源来自文件data.xml
myds.ReadXml(this.MapPath(Request.ApplicationPath + @"/data.xml"));
//判断是否存在缓存
if (Cache["BOOKS"] == null)
{
//创建缓存依赖
mydepen = new CacheDependency(this.MapPath(Request.ApplicationPath
+ @"/data.xml"));
//添加缓存项
Cache.Add("BOOKS", myds, mydepen, DateTime.Now.AddSeconds(10), TimeSpan.Zero,
CacheItemPriority.Normal, null);
}
}
}
注意:使用XML文件读取方法,必须添加XML操作方法所在的命名空间“System.Xml”。
切换回设计视图,再双击按钮控件,此时光标停靠在按钮的Click事件内。在此事件内书写代码,判断XML文件的数据是否已更新,如果已更新则给出提示,并重新添加缓存依赖项,否则直接从缓存读取GridView控件的数据。
在“Button1_Click”事件内书写的详细代码如下:
protected void Button1_Click(object sender, EventArgs e)
{
//判断缓存是否发生了变化
if (mydepen.HasChanged)
{
Response.Write("Sorry,数据发生了变化!上次修改时间是:" + mydepen.UtcLastModified);
}
//判断缓存项是否还在
if (Cache["BOOKS"] == null)
{
//重新设置缓存项
DataSet myds = new DataSet();
myds.ReadXml(this.MapPath(Request.ApplicationPath + @"/data.xml"));
mydepen = new CacheDependency(this.MapPath(Request.ApplicationPath + @"/ data.xml"));
Cache.Add("BOOKS", myds, mydepen, DateTime.Now.AddSeconds(10), TimeSpan.Zero,
CacheItemPriority.Normal, null);
}
GridView1.DataSource = Cache["BOOKS"];
GridView1.DataBind();
}
注意:当XML文件发生改变后,其实缓存依赖和缓存项都被移除了,必须重新定义。
按Ctrl+S组合键保存代码的修改。再按F5键运行程序,单击“获取数据”按钮,GridView就会显示XML文件的内容。
程序运行正常后,在后台修改XML文件的内容,然后再单击“获取数据”按钮,则出现更改数据的提示,同时GridView显示了新的内容。图16-4和图16-5是数据更改前和更改后的效果对比。
图16-4 初次获取的数据效果图 图16-5 更改数据后的显示效果图
16.4 数据库缓存依赖类:SqlCacheDependency类
数据库缓存依赖主要解决的是当数据库的内容发生改变时,如何及时通知缓存,并更新缓存中的数据的问题。本节就介绍如何使用SQL Server 2005和.NET 2.0实现数据库的缓存依赖。
16.4.1 功能说明
SqlCacheDependency类的使用需要结合SQL Server 2005数据库,目前还没有Oracle数据库的缓存依赖。
16.4.2 语法定义
SqlCacheDependency类的使用语法如下:
public class SqlCacheDependency : IDisposable
其中继承了接口“IDisposable”,此接口主要用来定义释放分配的非托管资源的方法。继承此接口必须实现方法Dispose,用来实现资源的释放。
SqlCacheDependency类主要的构造函数如下:
public SqlCacheDependency(string database,string table)
其中参数一代表要启用缓存的数据库,参数二表示缓存的表。在实际使用过程中,只需要指明缓存的数据库和表即可。
16.4.3 方法和属性
SqlCacheDependency类的方法和属性同CacheDependency类相同,主要有三个。
— HasChanged:判断数据库缓存依赖是否发生了变化。
— UtcLastModified:获取缓存依赖上次更改的时间。
— Dispose:释放缓存依赖所占用的资源。
这三个成员的使用方法同CacheDependency类的成员相似,本节不再赘述。
在下节要介绍的使用实例中,将不再使用代码的方式实现缓存依赖,而是使用“OutputCache”在.NET 2.0中提供的SqlCacheDependency参数实现数据库表的缓存。如果要使用编程的方式实现此功能,可参考CacheDependency类的实例。
16.4.4 使用SqlCacheDependency类的操作流程
要实现数据库缓存依赖,必须结合数据库的操作。在使用数据库缓存依赖前,必须进行5步操作。详细流程如图16-6所示。
只有具备了上述条件,才可以正常地使用数据库缓存依赖。下一节将结合这5步操作演示如何实现数据库的缓存依赖。
创建数据库链接
图16-6 使用数据库缓存依赖的流程
16.4.5 典型应用:获取数据库表最新数据的实例
本例要实现的功能是当数据库的内容发生变化时,保存在缓存中的数据项被更新。具体演示的步骤如下所述。
在数据库中创建数据库“testCache”。
在数据库“testCache”中添加表“CacheTable”,其信息如表16-3所示。
表16-3 CacheTable表的信息
字 段 名 | 字段类型 | 说 明 |
id | int | 自增长数据标识 |
Name | nvarchar(20) | 书名 |
bookPublish | nvarchar(50) | 出版社 |
Price | decimal(6,2) | 书的价格 |
为数据库启用缓存通知。打开“开始”|“所有程序”|“Microsoft Visual Studio 2005”|“Visual Studio Tools”|“Visual Studio 2005命名提示”菜单命令。
输入如下命令,其中“-ed”和“-et”分别代表启用缓存依赖数据库和启用缓存数据表。
aspnet_regsql.exe -S SqlServer服务器 -E -ed -d 数据库名称 -et -t 表名
注意如果使用的数据库验证方式是“SQL Server身份验证”,则需要使用如下的启动命令:
aspnet_regsql.exe -S SqlServer服务器 -U <Username> -P <Password> -ed -d 数据库名称 -et -t 表名
输入命令后,按回车键。如果执行成功,效果如图16-7所示。
打开VS2005,新建一个网站,命名为“SqlCacheDependency”。
按F5键运行程序,主要目的是生成一个默认的Web.Config文件。然后关闭运行的程序。
在Web.config中配置数据库连接字符串,代码如下:
<connectionStrings>
<add name="TestCacheConnectionString" connectionString="Data Source=CGJ-57F90 CCA64C\sqlexpress;Initial Catalog=testCache;Integrated Security=True" providerName= "System.
Data.SqlClient"/>
</connectionStrings>
图16-7 启用数据库缓存依赖成功的提示图
在“system.web”节点内,添加数据库缓存依赖的配置,详细代码如下所示。注意配置中的“connectionStringName”属性,要与前面创建的数据库连接字符串的名字相对应。
<caching>
<sqlCacheDependency enabled = "true" pollTime = "1000" >
<databases>
<add name="testCache"
connectionStringName="TestCacheConnectionString"
pollTime = "1000" />
</databases>
</sqlCacheDependency>
</caching>
按Ctrl+S组合键保存配置文件的更改。
打开默认生成的Default.aspx页,在设计视图中添加一个GridView控件,用来显示从数据库获取的数据。再添加一个Literal控件,主要用来显示时间,通过时间判断显示的是否是缓存中的数据。
为GridView配置数据源。单击其任务列表,在“选择数据源”下拉框中,单击“新建数据源”命令,打开数据源的配置向导。
在打开的数据源类型窗口中,选择“数据库”,单击“确定”按钮,出现选择连接字符串窗口,通过下拉列表选择刚刚创建的“TestCacheConnectionString”连接串。
单击“下一步”按钮,出现“配置Select语句”对话框,在“列”列表框中选择“*”,表示选中所有列。
单击“下一步”按钮出现测试查询对话框,然后单击“完成”按钮。
按F7键切换到到代码视图,在“Page_Load”事件中添加如下代码(主要是显示当前的时间,用来判断是否是缓存数据):
Literal1.Text = DateTime.Now.ToString();
按Ctrl+S组合键保存当前页的设计,再按F5键运行程序。当刷新页面时,可以看到时间是不断变化的,这说明数据并没有来自缓存。
打开Default.aspx页,在源代码视图的“<@page ”行下面,添加如下所示代码。其中使用的参数“SqlDependency”,就是用来添加数据库缓存依赖的。
<%@ OutputCache Duration="3600" SqlDependency="testCache:CacheTable" VaryByParam="none" %>
注意:Duration参数是表示缓存的过期时间,单位是毫秒。
按F5键运行程序,此时再刷新页面,发现当前的时间已经不再变化,因为整个页的数据被缓存了起来。
此时修改数据库的内容,然后刷新运行着的页面,可以发现,数据跟着发生了变化。这就是数据库缓存依赖的体现。当数据库内容更新时,不管缓存的时间有没有到,缓存的内容都会被更新。
16.5 Session和Cache的区别
以前实现数据的缓存有很多种方法,有客户端的Cookie,有服务器端的Session和Application。其中Cookie是保存在客户端的一组数据,主要用来保存用户名等个人信息。Session则保存对话信息。Application则是保存在整个应用程序范围内的信息,相当于全局变量。通常使用最频繁的是Session,那么Session和Cache又有什么区别呢?
本节结合使用经验,详细介绍Session缓存和Cache缓存的区别。
(1)最大的区别是Cache提供缓存依赖来更新数据,而Session只能依靠定义的缓存时间来判断缓存数据是否有效。
(2)即使应用程序终止,只要Cache.Add方法中定义的缓存时间未过期,下次开启应用程序时,缓存的数据依然存在。而Session缓存只是存在于一次会话中,会话结束后,数据也就失效了。
(3)Session容易丢失,导致数据的不确定性,而Cache不会出现这种情况。
(4)由于Session是每次会话就被加载,所以不适宜存放大量信息,否则会导致服务器的性能降低。而Cache则主要用来保存大容量信息,如数据库中的多个表。
(5)VS2005的测试版提供了将缓存保存在硬盘上的参数,但正式版中取消了这个功能,估计其在以后版本中会重新实现。而Session目前只能保存在内存中,对其性能有影响。
为了提高Cache的有效利用率,建议对于不经常改动的数据使用Cache。
16.6 小结
本章主要介绍了如何使用System.Web.Caching命名空间下的类,主要包括以下三个:Cache, CacheDependency和SqlCacheDependency。Cache类主要用来创建缓存项,主要针对的是数据不经常改变,但又使用频繁的数据表或文件。另两个类是.NET 2.0新添加的缓存依赖服务。通过文件依赖或数据库依赖,可以实现缓存数据的及时更新。
通过本章的学习,希望可以提高读者编写的网站的数据读取速度,节约带宽,为Web 2.0时代的到来打下坚实的基础。
MSDN上缓存概述:http://msdn2.microsoft.com/zh-cn/library/726btaeh(VS.80).aspx
一、页输出缓存
1.设置 ASP.NET 页缓存的两种方式
1.1 以声明方式设置 ASP.NET 页的缓存
以声明方式设置 ASP.NET 页的缓存的方法是在页中使用 @ OutputCache 指令,它的常用属性如下:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
Duration:设置缓存到期时间,单位:秒。
VaryByParam:可用来使缓存输出因查询字符串而异,多个查询字符用分号隔开。
VaryByControl:可用来使缓存输出因控制值而异。
VaryByHeader:可用来使缓存输出因请求的 HTTP 标头而异。
VaryByCustom:可用来使缓存输出因浏览器类型或您定义的自定义字符串而异。
CacheProfile:结合配置文件使用。
Location:设置页的可缓存性,值有Any,Client,Downstream,None,Server,ServerAndClient。
注:在使用 @ OutputCache 指令时,必须包括一个 VaryByParam 属性,否则将出现分析器错误。如果不希望使用 VaryByParam 属性提供的功能,请将它的值设置为“None”。
@ OutputCache 指令使用示例
①使用参数对页的各个版本进行缓存:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
注:如果要根据多个参数改变输出缓存,请包括以分号 (;) 作为分隔符的参数名称的列表;如果要根据所有的参数值来改变缓存,请将VaryByParam 属性设置为星号 (*);如果不要根据参数值来改变缓存,请将 VaryByParam 属性设置为"None"。
②使用 HTTP 标头对某页的各个版本进行缓存:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
注:如果要根据多个标头改变缓存的内容,请以分号 (;) 作为分隔符包括标头名称的列表;如果要根据所有标头值改变缓存的内容,请将VaryByHeader 属性设置为星号 (*)。
③使用请求浏览器缓存页的各个版本:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
④使用自定义字符串对页的各个版本进行缓存:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
注:还要在应用程序的 Global.asax 文件中,重写 GetVaryByCustomString 方法以指定自定义字符串的输出缓存行为。参考:http://msdn2.microsoft.com/zh-cn/library/5ecf4420(VS.80).aspx
⑤结合配置文件:
将以下 XML 添加为 system.web 元素的子项:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="AppCache1" enabled="true" duration="60"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
@ OutputCache 指令:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
使用这种方法我们可以从单个配置文件更改缓存行为,而无需编辑各个页面的 @ OutputCache 指令,并且还可以根据需要建立不同的缓存规则,再应用到各组单独页面中。
1.2 以编程方式设置 ASP.NET 页的缓存
以编程方式设置 ASP.NET 页的缓存的方法是在页的代码中,调用 Response 对象的 Cache 属性:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
Response.Cache.SetCacheability(HttpCacheability.Public); //设置页的可缓存性
Response.Cache.SetValidUntilExpires(true); //缓存忽略 Cache-Control 无效标头
使用示例
①使用参数对页的各个版本进行缓存:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
{
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1.0));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.VaryByParams["Zip"] = true;
}
注:如果要根据多个参数改变缓存的内容,请多次设置 VaryByParams 属性。
②使用 HTTP 标头对某页的各个版本进行缓存:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
{
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1.0));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.VaryByHeaders["Accept-Language"] = true;
}
注:如果要根据多个标头改变缓存的内容,需要在 VaryByHeaders 属性中设置多个值。如果要根据所有标头改变缓存的内容,请将VaryByHeaders["VaryByUnspecifiedParameters"] 设置为 true。
③使用请求浏览器缓存页的各个版本:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
{
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1.0));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.SetVaryByCustom("browser");
}
④使用自定义字符串对页的各个版本进行缓存:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
{
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1.0));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.SetVaryByCustom("minorversion");
}
说明:要在应用程序的 Global.asax 文件中,重写 GetVaryByCustomString 方法以指定自定义字符串的输出缓存行为。
2.页输出缓存的几种模型
2.1 整页缓存:当设置 ASP.NET 页缓存的位置发生在页面上时,即是整页缓存。
2.2 部分页缓存(控件缓存):当设置 ASP.NET 页缓存的位置发生在用户控件上时,即是控件缓存。
2.3 部分页缓存(缓存后替换):在整个缓存的页面上以声明方式使用 Substitution 控件或以编程方式使用 Substitution 控件 API 或以隐式方式使用 AdRotator 控件,即是采用了缓存后替换。
缓存后替换举例(以声明方式使用 Substitution 控件)
aspx代码:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
<br />
<asp:Substitution ID="Substitution1" runat="server" MethodName="NoCache" />
aspx.cs代码:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
{
Label1.Text = DateTime.Now.ToString();
}
protected static string NoCache(HttpContext context)
{
return DateTime.Now.ToString();
}
说明:Substitution 控件的 MethodName 属性值为一个方法的名称(本例为NoCache),对该方法的要求是它接受的参数类型必须为HttpContext且返回值类型为string,而且还必须为静态方法!
二、应用程序缓存
1.创建
方法1:Cache["CacheName"] = "CacheValue";
方法2:Cache.Insert(String key,object value,System.Web.Caching.CacheDependency dependencies,DateTime absoluteExpiration,TimeSpan slidingExpiration,System.Web.Caching.CacheItemPriority priority,System.Web.Caching.CacheItemRemovedCallback onRemoveCallback);
方法3:Cache.Add(String key,object value,System.Web.Caching.CacheDependency dependencies,DateTime absoluteExpiration,TimeSpan slidingExpiration,System.Web.Caching.CacheItemPriority priority,System.Web.Caching.CacheItemRemovedCallback onRemoveCallback);
Add方法和Insert方法的区别是Add 方法将返回您添加到缓存中的对象。另外,如果使用 Add 方法,并且缓存中已经存在与现有项同名的项,则该方法不会替换该项,并且不会引发异常。
创建示例
①通过使用 Insert 方法将项添加到缓存中:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
②通过指定依赖项向缓存添加项:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
Cache.Insert("CacheItem3", "Cached Item 3",new System.Web.Caching.CacheDependency(null, dependencies));
③将设有过期策略的项添加到缓存中:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
④将设有优先级设置的项添加到缓存中:
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
null, System.Web.Caching.Cache.NoAbsoluteExpiration,
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.High, null);
2.检索
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
cachedString = (string)Cache["CacheItem"];
if (cachedString == null)
{
cachedString = "Www.Mzwu.Com";
Cache.Insert("CacheItem", cachedString);
}
注:由于缓存中所存储的信息为易失信息,即该信息可能由 ASP.NET 移除,因此建议的开发模式是首先确定该项是否在缓存中。如果不在,则应将它重新添加到缓存中,然后检索该项。
3.移除
![程序代码](https://i-blog.csdnimg.cn/blog_migrate/58c53beb33fc757b1f6036e6c94a1479.gif)
FeedBack:
Flycoder
一、 前端优化
1. HTML静态化
2. 前端页面代码级别优化,详细可以参考Yahoo的相关文章,这里讨论有关HTML,javascript,CSShttp://developer.yahoo.com/performance/
http://websitetips.com/optimization/,这里又可以细分很多东西,有很多值得优化的地方。
3. 图片服务器分离
其主要思路如下:
减少一个页面访问所产生的http连接次数,减少Response流量,减少 DNS 查找,避免重定向 (Avoid Redirects),减少 DOM 元素数量,最小化 iframe 的数 量等等,总之可以在前端做足够的功夫。
二、服务器端优化
1. 缓存
缓存是性能提升的一个主要关注点,读内存的效率比数据库差别不再一个数量级上,缓存目前可选用的组件很多像大家常说的Memcached,而且不同语言都提供了自己的缓存机制。
对于大型网站缓存更是无处不在,客户端缓存、服务器端缓存、分布式缓存,细分又有数据缓存、普通对象缓存、XML缓存、文件缓存、数据库缓存、等等。在大型站点的架构设计中每一层都可以找到缓存的影子,可以说缓存无处不在。当然对缓存的使用也有很多需要注意的地方,不是所有东西都扔到了缓存里,我们设计的时候一定要看缓存的命中率,命中率高的应该一直保留在缓存中。很多缓存组件都对缓存做了分级,一级缓存,二级缓存,这是很好的机制,另外很多缓存算法都是我们在优化的时候可以参考。
2. 负载均衡
负载均衡是所有大中型网站必备的部署,大型网站每天上千万独立IP的访问量,一个Web服务器根本承担不了,网站后台必需有多台服务器共同工作。较早的负载均衡是DNS负载均衡,原理比较简单。稍微复杂一点的负载均衡,是反向代理,当外部有请求到代理服务器,代理服务器再将该请求均匀的转发到内网的服务器上,现在也有很多硬件产品可以去做负载均衡。镜像是相对比较简单的一些方法,目前采用的相对较多,如今同步更新技术日臻成熟,有很多成熟的解决方案和产品可选。负载均衡是Web站点架构设计需要着重考虑,扩展性在这里得到了良好的体现。
三、数据库端优化
目前虽然NO SQL 势头强劲,但是数据库还是主流。关于数据库优化也有很多种,大型网站都会考虑到分布式,数据库当然也不例外,分布式数据库解决的方法很简单,就是把数据分散在不同的数据库上。目前主要分布存储的方式都是按照一定的方式进行切分,主要是垂直切分(纵向)和水平切分(横向)两种方式。可以从不同方向理解,假设一张表数据较多可以拆分多张表可以说为水平切分,一张表字段较多可以把字段拆分成几张表称之为垂直切分。当然也可以从业务方面去理解:把当前站点不同的业务独立出来存储称为垂直切分,不切分业务,把业务做个一个整体但是按照某种规则分布存储称为水平切分。不管怎么理解其主体思想就是化整为零,以求达到最好的性能。
分布式存储也要考虑负载均衡的问题,目前也有很多相关可以参考的做法,比较常见的有散列方式,或者全局方式,这里都需要仔细考虑到扩容的问题,另外我也需要考虑到分布式存储的缺点,像搜索查询等等,另外也可以结合内存数据库还有一些其他相关的做法从不同方面去优化。
网站可优化的地方很多很多,每部分也都可以写出一本书去阐述,我只是根据目前我了解的做简单总结,肯定还会漏掉很多地方,大家可以补充。希望对大家有所帮助。
回复 引用 查看
Posted on 2009-04-08 09:52 yiki 阅读(504) 评论(0) 编辑 收藏 网摘 所属分类: ASP.NET
前言
本文主要是对《ASP.NET 2.0开发指南》——<数据缓存>章节内容的提取并略有补充。
参考资料
1. 《ASP.NET 2.0开发指南》
2. .NET 2.0 SqlDependency快速上手指南
支持数据库
SQL SERVER 7.0/2000/2005版本
正文
一、SQL SERVER 7.0/2000和SQL SERVER 2005的简介及比较
1.1 SQL SERVER 7.0/2000
SQL SERVER 7.0/2000没有提供内置的支持数据缓存依赖的功能,所以只能通过采用添加特定数据库表、触发器等方式,通过后台不断轮询数据库来检查数据更改。当在数据表上执行INSERT、UPDATE、 DELETE操作时将自动发出更改通知,所以只能监测到表级,具体到哪一行是没法跟踪的。
使用方法步骤:
1.1.1 使用aspnet_regsql命令行或SqlCacheDependencyAdmin来配置连接数据库。
1.1.1.1 ALTER DATABASE <DatabaseName> SET ENABLE_BROKER;
aspnet_regsql -S <server> -U sa -P sa -d <database> -ed 启动数据库的数据缓存依赖功能
aspnet_regsql -S <server> -U sa -P sa -d <database> -t <table> -et 启动数据表的数据缓存依赖功能
1.1.1.2
SqlCacheDependencyAdmin.EnableNotifications(connectionString); //启动数据库的数据缓存依赖功能
SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString, table); //启用数据表缓存
推荐这段代码写在Global.asax的Application_Start方法中,以便应用程序启动的时候就启用数据库和数据表的缓存依赖功能。
1.1.2 配置Web.config
<sqlCacheDependency enabled="true" pollTime="10000">配置在<sytem.web>下的<caching>结点下,只有一个数据库的话不必指定下一级<database>结点
1.1.3 应用程序数据缓存中使用(还可以在数据源控件、输出缓存整个页面时使用,这里就不介绍了,下同)
SqlCacheDependency scd = new SqlCacheDependency("数据库名称","表名");
Cache.Insert(...,scd,...);
1.2 SQL SERVER 2005
内置支持SQL数据缓存依赖,内置通知传递服务,能够提供更小粒度的数据更改监测,使用和配置简单。
使用方法步骤:
1.2.1 检测是否已经启用Service Broker
Select DATABASEpRoPERTYEX('数据库名称','IsBrokerEnabled') -- 1 表示已经启用 0 表示没有启用
这个地方我看有些朋友翻译的成“是否能启用”,这是不对的,这里我把英文原文帖出来:“This can be checked by calling "Select databasepropertyex('db Name', 'IsBrokerEnabled')". A '1' means that the broker is enabled. A '0' means that the broker is not enabled. ”。
依据我的经验,如果直接在当前SqlServer2005上新建一个数据库的话,默认是打开的,如果是从其他地方数据库导过来的,导入之后默认关闭了。(可能有不准确,大家可以自己试验一下测试一下)。如果已经打开可直接调到1.2.2。
1.2.1.1 启用Service Broker
ALTER DATABASE 数据库名称 SET ENABLE_BROKER;
1.2.2 在实现基于服务的SQL数据缓存依赖过程中,需要显式调用SqlDependency.Start来启动接受依赖项更改通知的侦听器。
SqlDependency.Start(connectionString); //推荐将这段代码加到Global.asax的Application_Start方法中,
SqlDependency.Stop(connectionString); //用于关闭,可加在Global.asax的Application_End方法中。
1.2.3 应用程序数据缓存中使用
SqlCommand cmd = new SqlCommand(sql,conn);
SqlCacheDependency scd = new SqlCacheDependency(cmd);
Cache.Insert(...,scd,...);
注意:
a). 必须设置完全限定名称的数据表。即表名前面需要加所有者,如dbo.test。
b). 必须明确设置所访问数据库列名称,不能使用“*”。
c). 必须保证不是聚合函数。如COUNT、MAX等。
回复 引用 查看
SQL SERVER 7.0/2000
SQL SERVER 2005
实现机制
轮询
通知传递服务(Service Broker)
是否需要配置启用
需要
不需要,内置支持
数据更改检测
限于表级更改监测
表级、行级更改监测
并且很明显,SQL SERVER 2005的缓存机制更加高效。另外,SqlCacheDependency类还特别结合SQL SERVER 2005 进行了优化:
a). 使用SQL SERVER 2005 时,SqlCacheDependency类支持与System.Data.SqlClient.SqlDependency类进行集成。应用程序可创建SqlDependency对象,并通过OnChanged事件处理程序接受通知进行注册。这样,应用程序不仅可以使用Sql server 2005的查询通知机制来监测使用SQL查询结果无效的数据更改,并将缓存对象从缓存中移除,而且还可以轻松获取数据更改通知,以便刷新缓存。(从这里可以看出,当触发onRemoveCallback委托的时候,数据已经从缓存里面删除了,这样一来可以手动在委托里面添加缓存,或者干脆设置成null,让他下次调用的时候再缓存。)
b). 不仅向应用程序添加缓存依赖项,还可以与@OutputCache指令一起使用,以生成依赖于SqlServer数据库表的输出缓存的页面或用户控件。对于用户控件,@OutputCache指令不支持使用SQL SERVER 2005 的查询通知(即onRemoveCallback委托)。
二、System.Web.Caching.Cache Insert和Add区别
2.1 Add方法
object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);
2.2 Insert方法
void Insert(string key, object value);
void Insert(string key, object value, CacheDependency dependencies);
void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration);
void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback);
void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);
2.3 比较、区别
a). Insert方法支持5种重载,使用灵活,而Add方法必须提供7个参数;
b). Add方法可以返回缓存项的数据对象,Insert 返回Void;
c). 添加重复缓存情况下,Insert会替换该项,而Add方法会报错。
三、 CacheDependency、AggregateCacheDependency、SqlCacheDependency
3.1 CacheDependency是AggregateCacheDependency和SqlCacheDependency的父类。主要用于在应用程序数据缓存对象与文件、缓存键、文件或缓存键的数组或另外一个CacheDependency对象之间建立依赖关系。CacheDependency监视依赖关系比便在任何对象更改时自动移除缓存对象。CacheDependency可以监测一组(到文件或目录的)文件路径的更改情况。
3.2 AggregateCacheDependency主要用于实现聚合缓存依赖。如一笔数据同时对两个表进行缓存依赖,一旦其中任何一个表数据更改缓存将失效。
3.3 SqlCacheDependency将应用程序数据缓存对象、页面输出缓存、数据源控件等与指定SQL Server数据库表或Sql Server 2005 查询结果之间建立缓存依赖关系,在表发生更改(Sql Server 2005 行级别更改)时,自动从缓存中删除和重新添加与该表关联的缓存对象。一般而言:
SqlCacheDependency (SqlCommand) 用于SQL SERVER 2005
SqlCacheDependency (数据库名, 表名) 用于SQL SERVER 7.0/2000
vs2005中启用数据库缓存依赖
aspnet_regsql.exe -S localhost -U sa -P sa -d hnfms -ed
aspnet_regsql.exe -S localhost -U sa -P sa -d hnfms -t Applys -et
数据库端启用缓存依赖
ALTER DATABASE hnfms SET ENABLE_BROKER;
数据库端查询是否启用缓存依赖
Select DATABASEpRoPERTYEX('hnfms','IsBrokerEnabled') -- 1 表示已经启用 0 表示没有启用
Web.config中配置
<caching>
<sqlCacheDependency enabled="true" pollTime="1000">
<databases>
<!--这里配置缓存依赖数据库的连接,
如果库名填写与实际的库名不正确的话
会出现"调用的目标发生异常"的错误-->
<add name="hnfms" connectionStringName="hnfmsConnectionString"/>
</databases>
</sqlCacheDependency>
</caching>
Gload.asxm中配置
void Application_Start(object sender, EventArgs e)
{
// 在应用程序启动时运行的代码
System.Data.SqlClient.SqlDependency.Start(System.Configuration.ConfigurationManager.ConnectionStrings["hnfmsConnectionString"].ConnectionString);
}
void Application_End(object sender, EventArgs e)
{
// 在应用程序关闭时运行的代码
System.Data.SqlClient.SqlDependency.Stop(System.Configuration.ConfigurationManager.ConnectionStrings["hnfmsConnectionString"].ConnectionString);
}
回复 引用 查看
有时候总听到网友说网站运行好慢,不知如何是好;有时候也总见到一些朋友写的网站功能看起来非常好,但访问性能却极其的差。没有“勤俭节约”的意识,势必会造成“铺张浪费”。如何应对这种情况,充分利用系统缓存则是首要之道。
系统缓存有什么好处呢?举个简单的例子,你想通过网页查询某些数据,而这些数据并非实时变化,或者变化的时间是有期限的。例如查询一些历史数据。那么每个用户每次查的数据都是一样的。如果不设置缓存,ASP.NET也会根据每个用户的请求重复查询n次,这就增加了不必要的开销。所以,可能的情况下尽量使用缓存,从内存中返回数据的速度始终比去数据库查的速度快,因而可以大大提供应用程序的性能。毕竟现在内存非常便宜,用空间换取时间效率应该是非常划算的。尤其是对耗时比较长的、需要建立网络链接的数据库查询操作等。
缓存功能是大型网站设计一个很重要的部分。由数据库驱动的Web应用程序,如果需要改善其性能,最好的方法是使用缓存功能。
系统缓存全解析文章索引
系统缓存全解析1:系统缓存的概述
系统缓存全解析2:页面输出缓存
系统缓存全解析3:页面局部缓存
系统缓存全解析4:应用程序数据缓存
系统缓存全解析5:文件缓存依赖
系统缓存全解析6:数据库缓存依赖
系统缓存全解析7:第三方分布式缓存解决方案 Memcached和Cacheman
15.4.1 缓存的分类
从分布上来看,我们可以概括为客户端缓存和服务器端缓存。如图15-1所示:
图15-1 缓存的分类
客户端缓存—— 这点大家都有直观的印象。比如你去一个新的网站,第一次可能要花一阵子时间才能载入整个页面。而以后再去呢,时间就会大大的缩短,原因就在于这个客户端缓存。现在的浏览器都比较智能,它会在客户机器的硬盘上保留许多静态的文件,比如各种gif,jpeg文件等等。等以后再去的时候,它会尽量使用本地缓存里面的文件。只有服务器端的文件更新了,或是缓存里面的文件过期了,它才会再次从服务器端下载这些东西。很多时候是IE替我们做了这件事情。
服务器端缓存—— 有些东西没法或是不宜在客户端缓存,那么我们只好在服务器端想想办法了。服务器端缓存从性质上看,又可以分为两种。
(1)静态文件缓存
好多页面是静态的,很少改动,那么这种文件最适于作静态缓存。现在的IIS 6.0这部分内容是直接存放在Kernel的内存中,由HTTP.SYS直接管理。由于它在Kernel Space,所以它的性能非常的高。用户的请求如果在缓存里面,那么HTTP.SYS直接将内容发送到network driver上去,不需要像以前那样从IIS的User space的内存copy到Kernel中,然后再发送到TCP/IP stack上。Kernel level cache几乎是现在高性能Web server的一个必不可少的特性。
(2)动态缓存
动态缓存是比较有难度的。因为你在缓存的时候要时刻注意一个问题,那就是缓存的内容是不是已经过时了。因为内容过时了可能会有很严重的后果。比如网上买卖股票的网站。你给别人提供的价格是过时的,那人家非砍了你不可。缓存如何发现自己是不是过时就是一个非常复杂的问题。
在ASP.NET中,常见的动态缓存主要有以下几种手段:
Ø 传统缓存方式
Ø 页面输出缓存。
Ø 页面局部缓存。
Ø 利用.NET提供的System.Web.Caching 缓存。
Ø 缓存依赖。
15.4.2 传统缓存方式
比如将可重复利用的东西放到Application或是Session中去保存。
Session["Style"] = val;
Application["Count"] = 0;
(选自《亮剑.NET:.NET深入体验与实战精要》第15章)