[转载]缓存增强用户体验感 – csdbfans – 博客园.
搞Web开发的人,都会听说过缓存,开发中偶尔会遇到换图片、修改引入进来的脚本文件或者是替换Flash文件,你会发现运行出来的结果不变,这时候你肯定也会想过是缓存的原因,会把浏览器的缓存给清除掉。步骤可以如下清除浏览器缓存:
今天想写写ASP.NET缓存,搞Web开发,不使用缓存是不可能的。
缓存有分客户端缓存与服务端缓存,但是通常使用服务端缓存。因为客户端的请求都是服务端来响应,那么在服务端来做缓存的话,客户端的请求都可以由缓存来响应。从而使响应的速度更快。缓存是什么?它就像一个时间片段的数据副本,在缓存的有效时间内,客户的请求,服务器都只用相同的数据副本来进行响应。
就因为缓存的这种特征,它使得请求后的响应时间更短,有效提高了服务器的性能,降 低带宽的成本。总之,相同的环境下,使用缓存与不使用缓存,在响应时间比较长的情况下,使用缓存的响应速度会让你惊叹不已。但是缓存虽棒,也有不足之处。 提高了响应速度,带来了数据的不准确性。因为前面也说了缓存是一个时间片段的数据副本,也就是说数据经过增加、删除、更改等加工之后,显示给用户看的效果 还是原来那样。这有时候会让人很恼火,尤其像我这样急性子的人。但使用缓存依赖就可以解决此问题。
同一个人,对于某些人来说,是好人,对于某些人来说,是坏人。所以对事对人来说, 总不能以偏盖全。避开缺点,发挥优势,才是我们需要做的。缓存可以使用在加工频率要求不是特别高的地方 。假如对于用户来说,数据实时性并不特别重要,也 就是对时间的制约不是特别高的话,那么使用缓存确实可以增速不少。
下面我们来看看服务端缓存与客户端缓存。
服务端缓存:
(1)Session:针对小量数据,服务于单个用户,默认失效时间为20分钟。
包括三种实现方式,分别是:
=>InProc方式:
数据存储在aspnet_wp.exe 进程中,数据会因为IIS的重启而丢失。
=>StateServer方式 :
较InProc不同,可以存储于不同的服务器中。
=>SQLServer:
数据存储于数据库中,数据不会因为IIS的重启而丢失。
后两种方法与InProc最大的区别在于,我们要确保缓存的数据是可序列化的。否则只能用第一种方式,为此我们要仔细分析从而选出最适合自己的方式.
使用方法:
//存数据
Session[“key”] = value;
//取数据
Object value = Session[“key”]
(2)Application:任意数据大小,服务于所有用户,拥有整个应用程序的生命周期。通常是针对小数据存储,像实现网站访问量等。
与Session的使用方法相同:
//存数据
Application[“key”] = value;
//取数据
Object value = Application[“key”];
(3)Cache:任意数据大小,服务于所有用户,程序指定生命周期。
移除Cache,我们可以使用Cache.Remove(“key”),也可以根据缓存依赖关系来让Cache失效。当依赖的关系有改动时,此时Cache会自动失效。
=》缓存依赖:缓存的生命周期依赖于数据来源的变化,缓存依赖有多种,限于篇幅,只介绍下面两种。
I、依赖于文件或文件夹:当磁盘上的一个文件或文件夹发生变化时(修改或者是删除)自动让Cache失效。使用缓存依赖,你可以实例化微软的CacheDependency对象,并给对象传递文件的路径或者是文件夹的路径。如果是文件夹的路径,它会监视该文件夹下的所有文件和里面第一级子文件夹。
string cacheData="缓存内容"; CacheDependency fileDependency =new CacheDependency(Server.MapPath("test.xml")); Cache.Insert("ERROR_INFO", cacheData, fileDependency);
II、依赖于数据库:当数据库中的相关数据被修改时自动让Cache失效。
依赖于文件或文件夹,微软提供CacheDependency对象,但是依赖于数据库,则需要使用另一个对象SQLCacheDependcy。
需要结合SQL Server 2005数据库,目前还没有Oracle数据库的缓存依赖。
使用数据库依赖,ASP.NET可以按如下方式实现:
第一步:web.config两配置
一配置数据库连接字符串:
<configuration> ... <connectionStrings> <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" /> </connectionStrings> ... </configuration>
二配置缓存依赖数据库(缓存数据库依赖主要是说明依赖哪个数据库,下面的connectionStringName值与一中的name是一致的)
<system.web>…<caching><sqlCacheDependency enabled = “true” pollTime = “1000” ><databases><add name=”testCache“connectionStringName=”ApplicationServices“pollTime = “1000” /></databases></sqlCacheDependency></caching>…</system.web>第二步:需要使用缓存数据库的ASPX页面再增加如下语句即可:
<%@ Page Title=”主页” Language=”C#” MasterPageFile=”~/Site.master” AutoEventWireup=”true”
CodeBehind=”Default.aspx.cs” Inherits=”SqlCacheDenpendcy._Default” %><%@ OutputCache Duration=”3600″ SqlDependency=”testCache:CacheTable” VaryByParam=”none” %>
(4)ASP.NET 页面输出缓存 —ASPX和ASCX页面
在Web站点中,最简单直接有效的方式可以使用页面输出缓存。通过缓存页面来输 出,数据则不像依赖缓存那么准确,因为页面是指定时间失效。这里的页面包括ASPX页面也包括ASCX用户控件页面。ASPX页面是整页面缓存,而 ASCX用户控件页面则是局部缓存。两者的使用方式一样。
代码跟与第数据库依赖的第二步类似:
<%@ Page Title=”主页” Language=”C#” MasterPageFile=”~/Site.master” AutoEventWireup=”true”
CodeBehind=”Default.aspx.cs” Inherits=”SqlCacheDenpendcy._Default” %><%@ OutputCache Duration=”60″ VaryByParam=”empNum” Location=”Server“%>
参数解释:
参数 说明 备注 Duration 页或用户控件进行缓存的时间(以秒计)。 在页或用户控件上设置该特性为来自对象的 HTTP 响应建立了一个过期策略,并将自动缓存页或用户控件输出。 此特性必选。 如果未包含该属性,将出现分析器错误。 除非你的Location=None,可以不添加此属性,其余时候都是必须的。
Location OutputCacheLocation 枚举值之一。 默认值为 Any。
Location当被设置为None时,其余的任何设置将不起作用;
Any——页面被缓存在浏览器、代理服务器端和web服务器端;
Client——缓存在浏览器;
DownStream——页面被缓存在浏览器和任何的代理服务器端;
None——页面不缓存;
ServerAndClient——页面被缓存在浏览器和web服务器端。包含在用户控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。 CacheProfile 与该页关联的缓存设置的名称。 这是可选特性,默认值为空字符串 (“”)。 包含在用户控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。 在页中指定此属性时,属性值必须与 outputCacheSettings 节下面的 outputCacheProfiles 元素中的一个可用项的名称匹配。 如果此名称与配置文件项不匹配,将引发异常。参考:CacheProfile实例 NoStore 一个布尔值,它决定了是否阻止敏感信息的二级存储。 包含在用户控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。 将此特性设置为 true 等效于在请求期间执行以下代码:
Response.Cache.SetNoStore();ProviderName 一个字符串值,标识要使用的自定义输出缓存提供程序。 此属性仅在用户控件(.ascx 文件)中受到支持。 它不受包含在 ASP.NET 页(.aspx 文件)中的 @ OutputCache 指令的支持。 Shared 一个布尔值,确定用户控件输出是否可以由多个页共享。 默认值为 false。 包含在 ASP.NET 页(.aspx 文件)中的 @ OutputCache 指令不支持此特性。 SqlDependency 标识一组数据库/表名称对的字符串值,页或控件的输出缓存依赖于这些名称对。 请注意,SqlCacheDependency 类监视输出缓存所依赖的数据库中的表,因此当更新表中的项时,使用基于表的轮询时将从缓存中移除这些项。 如果以值 CommandNotification 使用通知(在 Microsoft SQL Server 2005 中),则最终会使用 SqlDependency 类向 SQL Server 2005 服务器注册查询通知。 SqlDependency 特性的 CommandNotification 值仅在网页 (.aspx) 中有效。 用户控件只能将基于表的轮询用于 @ OutputCache 指令。 VaryByCustom 任何表示自定义输出缓存要求的文本。 如果特性的赋值为 browser,缓存将随浏览器名称和主要版本信息的不同而异。 如果输入自定义字符串,则必须在应用程序的 Global.asax 文件中重写 GetVaryByCustomString 方法。 VaryByHeader 分号分隔的 HTTP 标头列表,用于使输出缓存发生变化。 将该特性设为多标头时,对于每个指定标头组合,输出缓存都包含一个不同版本的请求文档。
Accept-Language——代表请求页面中用户最希望的有优先级顺序的人类语言列表;
User-Agent——代表请求页面设备的类型;
Cookie——代表当前域名下创建的浏览器的cookie项。设置 VaryByHeader 特性将启用在所有 HTTP 1.1 版缓存中缓存项,而不仅仅在 ASP.NET 缓存中进行缓存。 用户控件中的 @ OutputCache 指令不支持此特性。
例如:设置VaryByHeader=”Accept-Language”。
当网站有多种语言版本时,可以为每种语言都进行缓存。VaryByParam 分号分隔的字符串列表,用于使输出缓存发生变化。 默认情况下,这些字符串对应于使用 GET 方法特性发送的查询字符串值,或者使用 POST 方法发送的参数。 将该特性设置为多个参数时,对于每个指定参数组合,输出缓存都包含一个不同版本的请求文档。 可能的值包括 none、星号 (*) 以及任何有效的查询字符串或 POST 参数名称。 在 ASP.NET 页和用户控件上使用 @ OutputCache 指令时,需要此特性或 VaryByControl 特性。 如果没有包含它,则发生分析器错误。 如果不希望通过指定参数来改变缓存内容,请将值设置为 none。 如果希望通过所有的参数值改变输出缓存,请将特性设置为星号 (*))。
例如:
如果命令设置为:
<%@ OutputCache Duration=”60″ VaryByParam=”ProductType” %>
当 请求路径 bitauto.com/test.aspx?ProductType=1发生时,会建立缓存当ProductType的值变为2时,系统会建立新的缓 存,但是原来的缓存在有效期内并不会失效。相当于为不同的ProductType值建立了不同版本的缓存。如果熟悉.Net数据缓存的话,很类似于下面的 用法。
Cache.Add(“productType1”,cachedObject)
Cache.Add(“productType2”,cachedObject)VaryByControl 分号分隔的字符串列表,用于改变用户控件的输出缓存。 这些字符串代表用户控件中声明的 ASP.NET 服务器控件的 ID 属性值。 在 ASP.NET 页和用户控件上使用 @ OutputCache 指令时,需要此特性或 VaryByParam 特性。
例如下面:根据页面上下拉列表控件的选择的值不同进行不同的缓存输出
<%@ OutputCache Duration=”100″ VaryByControl=”dropTest”%>VaryByContentEncodings 以分号分隔的字符串列表,用于更改输出缓存。 将 VaryByContentEncodings 特性用于 Accept-Encoding 标头,可确定不同内容编码获得缓存响应的方式。
客户端缓存:
上面介绍了部分服务端缓存的方法,但有的时候我们为了提高服务器的性能我们也需要把数据缓存到客户端。使用这种缓存机制,可以适当缓解服务器压力,不过在客户端缓存数据会有一定的安全性问题。
Cookies:在Web站点中应用非常广,它可以非常方便的在客户端与服务器端之间进行相互访问,最大只能支持4KB,所以一般只能保存小数据。可以储存到客户端的硬盘或内存。
if (this.Request.Cookies["key"] == null) { this.Response.Cookies.Add(new HttpCookie("key","test")); } else { this.Response.Write(this.Request.Cookies["key"].Value); }
题外话,客户端缓存及服务端缓存,在网上查找了很多相关的文章,内容都很丰富,也很详细,通过整理学习,并写成博客,我觉得这种学习方式挺好的。虽然写作能力有高下之分,但是长期以往地坚持,笨鸟也可以先飞。至此,本文告一段落,希望能抛我的砖引大家的玉 🙂