zoukankan      html  css  js  c++  java
  • 【缓存】系统缓存全解析 (上)

         有时候总听到网友说网站运行好慢,不知如何是好;有时候也总见到一些朋友写的网站功能看起来非常好,但访问性能却极其的差。没有“勤俭节约”的意识,势必会造成“铺张浪费”。如何应对这种情况,充分利用系统缓存则是首要之道。

        系统缓存有什么好处呢?举个简单的例子,你想通过网页查询某些数据,而这些数据并非实时变化,或者变化的时间是有期限的。例如查询一些历史数据。那么每个用户每次查的数据都是一样的。如果不设置缓存,ASP.NET也会根据每个用户的请求重复查询n次,这就增加了不必要的开销。所以,可能的情况下尽量使用缓存,从内存中返回数据的速度始终比去数据库查的速度快,因而可以大大提供应用程序的性能。毕竟现在内存非常便宜,用空间换取时间效率应该是非常划算的。尤其是对耗时比较长的、需要建立网络链接的数据库查询操作等。

    缓存功能是大型网站设计一个很重要的部分。由数据库驱动的Web应用程序,如果需要改善其性能,最好的方法是使用缓存功能。

    1、缓存的分类

    从分布上来看,我们可以概括为客户端缓存和服务器端缓存。

    o_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 缓存。
    •   缓存依赖。

    2、页面输出缓存

    页面输出缓存是最为简单的缓存机制,该机制将整个ASP.NET页面内容保存在服务器内存中。当用户请求该页面时,系统从内存中输出相关数据,直到缓存数据过期。在这个过程中,缓存内容直接发送给用户,而不必再次经过页面处理生命周期。通常情况下,页面输出缓存对于那些包含不需要经常修改内容的,但需要大量处理才能编译完成的页面特别有用。需要读者注意的是,页面输出缓存是将页面全部内容都保存在内存中,并用于完成客户端请求。

    在ASP.NET中页面缓存的使用方法非常的简单,只需要在aspx页的顶部加这样一句声明即可:

    <%@ OutputCache Duration="60" VaryByParam="none" %>

    Duration

    缓存的时间(秒)。这是必选属性。如果未包含该属性,将出现分析器错误。

    隐藏行号 复制代码
    1. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
    2. <%@ OutputCache Duration="60" VaryByParam="none" %>
    3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    4. <html xmlns="http://www.w3.org/1999/xhtml">
    5. <head runat="server">
    6.     <title></title>
    7. </head>
    8. <body>
    9.     <form id="form1" runat="server">
    10.     <%DateTime.Now.ToString(); %>
    11.     </form>
    12. </body>
    13. </html>
    如果不加<%@ OutputCache Duration="60" VaryByParam="none" %>,每次刷新页面上的时间每次都是在变。而加了缓存声明以后,每次刷新页面的时间并不变化,60秒后才变化一次,说明数据被缓存了60秒。

    VaryByParam

    是指页面根据使用 POST 或 GET 发送的名称/值对(参数)来更新缓存的内容,多个参数用分号隔开。如果不希望根据任何参数来改变缓存内容,请将值设置为 none。如果希望通过所有的参数值改变都更新缓存,请将属性设置为星号 (*)。

    例如: http://localhost:1165/16-4-3/WebForm1.aspx?p=1
    则可以在WebForm1.aspx页面头部声明缓存:<%@ OutputCache Duration="60" VaryByParam="p" %>

    以上代码设置页面缓存时间是60秒,并根据p参数的值来更新缓存,即p的值发生变化才更新缓存。

    如果一直是WebForm1.aspx?p=1访问该页,则页面会缓存当前数据,当p=2时又会执行后台代码更新缓存内容。

    如果有多个参数时,如:http://localhost:1165/16-4-3/WebForm1.aspx?p=1&n=1

    可以这样声明:<%@ OutputCache Duration="60" VaryByParam="p;n" %>

    除此之外,@OutputCache 还有一些其他的属性。@OutputCache指令中的属性参数描述如下:

    <%@ OutputCache Duration="#ofseconds"

    Location="Any | Client | Downstream | Server | None |

    ServerAndClient "

    Shared="True | False"

    VaryByControl="controlname"

    VaryByCustom="browser | customstring"

    VaryByHeader="headers"

    VaryByParam="parametername"

    CacheProfile="cache profile name | ''"

    NoStore="true | false"

    SqlDependency="database/table name pair | CommandNotification"

    %>

    CacheProfile

    用于调用Web.config配置文件中设置的缓存时间。这是可选属性,默认值为空字符 ("")。

    例如:

    在Web.config中加入配置:

    隐藏行号 复制代码
    1. <caching>
    2.   <outputCacheSettings>
    3.     <outputCacheProfiles>
    4.       <add name="CacheTest" duration="60" />
    5.     </outputCacheProfiles>
    6.   </outputCacheSettings>
    7. </caching>

    页面中声明:

    <%@ OutputCache CacheProfile="CacheTest"  VaryByParam="none" %>

    注意:

    包含在用户控件(.ascx 文件)中的 @ OutputCache 指令不支持此属性。在页中指定此属性时,属性值必须与 outputCacheSettings 节下面的 outputCacheProfiles 元素中的一个可用项的名称匹配。如果此名称与配置文件项不匹配,将引发异常。

    如果每个页面的缓存时间相同,则不需要每个页面设置,而是通过统一一个地方控制,这样就可以更好的统一控制所有页面的缓存时间。如果想改变缓存时间,只需要改一下web.config的配置信息即可,而不用每个页面去修改。

    VaryByControl

    通过用户控件文件中包含的服务器控件来改变缓存(值是控件ID,多控件用分号隔开)。

    在 ASP.NET 页和用户控件上使用 @ OutputCache 指令时,需要该属性或 VaryByParam 属性。

    隐藏行号 复制代码
    1. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
    2. <%@ OutputCache Duration="60" VaryByParam="none" VaryByControl="DropDownList1" %>
    3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    4. <html xmlns="http://www.w3.org/1999/xhtml">
    5. <head runat="server">
    6.     <title></title>
    7. </head>
    8. <body>
    9.     <form id="form1" runat="server">
    10.     <%DateTime.Now.ToString(); %>
    11.     <asp:DropDownList ID="DropDownList1" AutoPostBack="true" runat="server">
    12.         <asp:ListItem>ddddddd</asp:ListItem>
    13.         <asp:ListItem>eeeeee</asp:ListItem>
    14.     </asp:DropDownList>
    15.     </form>
    16. </body>
    17. </html>

    以上代码设置缓存有效期是60秒,并且页面不随任何GET或POST参数改变(即使不使用VaryByParam属性,但是仍然需要在@ OutputControl指令中显式声明该属性)。如果用户控件中包含ID属性为“DropDownList1”的服务器控件(例如下拉框控件),那么缓存将根据该控件的变化来更新页面数据。

    页面输出缓存API

    Response类的Cache属性用于获取页面缓存策略。该方式的核心是调用System.Web.HttpCachePolicy。该类主要包含用于设置缓存特定的HTTP标头的方法和用于控制ASP.NET页面输出缓存的方法。与.NET Framework 1.x中的HttpCachePolicy类相比,.NET Framework 2.0中的HttpCachePolicy类得到了扩充和发展。主要是增加了一些重要方法,例如,SetOmitVarStar方法等。由于HttpCachePolicy类方法众多,下面简要说明几个常用方法。

    SetExpires方法

    用于设置缓存过期的绝对时间。它的参数是一个DataTime类的实例,表示过期的绝对时间。

    隐藏行号 复制代码
    1. protected void Page_Load(object sender, EventArgs e)
    2. {
    3.     // 通过API设置缓存
    4.     //相当于@OutputCache指令中的Duration属性
    5.     Response.Cache.SetExpires(DateTime.Now.AddSeconds(10));
    6.     Response.Cache.SetExpires(DateTime.Parse("6:00:00PM"));
    7. }

    如上代码,第一行代码表示输出缓存时间是60秒,并且页面不随任何GET或POST参数改变,等同于“<%@ OutputCache Duration="60" VaryByParam="none" %>”。第二行代码设置缓存过期的绝对时间是当日下午6时整。

    SetLastModified方法

    用于设置页面的Last-Modified HTTP标头。Last-Modified HTTP标头表示页面上次修改时间,缓存将依靠它来进行计时。如果违反了缓存限制层次结构,此方法将失败。该方法的参数是一个DataTime类的实例。

    SetSlidingExpiration方法

    该方法将缓存过期从绝对时间设置为可调时间。其参数是一个布尔值。当参数为true时,Cache-Control HTTP标头将随每个响应而更新。此过期模式与相对于当前时间将过期标头添加到所有输出集的IIS配置选项相同。当参数为False时,将保留该设置,且任何启用可调整过期的尝试都将静态失败。此方法不直接映射到HTTP标头。它由后续模块或辅助请求来设置源服务器缓存策略。

    SetOmitVaryStar方法

    ASP.NET 2.0新增的方法。用于指定在按参数进行区分时,响应是否应该包含vary:*标头。方法参数是一个布尔值,若要指示HttpCachePolicy不对其VaryByHeaders属性使用*值,则为true;否则为false。

    SetCacheability方法

        用于设置页面的Cache-Control HTTP标头。该标头用于控制在网络上缓存文档的方式。该方法有两种重载方式,所不同的是参数。一种重载方法的参数是HttpCacheability枚举值,包括NoCache、Private、Public、Server、ServerAndNoCache和ServerAndPrivate(有关这些枚举值的定义,可参考MSDN)。另一种方法的参数有两个,一个参数是HttpCacheability枚举值,另一个参数是字符串,表示添加到标头的缓存控制扩展。需要注意的是,仅当与Private或NoCache指令一起使用时,字段扩展名才有效。如果组合不兼容的指令和扩展,则此方法将引发无效参数异常。

    4、页面局部缓存

      有时缓存整个页面是不现实的,因为页的某些部分可能在每次请求时都需要变化。在这些情况下,只能缓存页的一部分。顾名思义,页面部分缓存是将页面部分内容保存在内存中以便响应用户请求,而页面其他部分内容则为动态内容。页面部分缓存的实现包括两种方式:控件缓存和替换后缓存

    1. 控件缓存(也称为片段缓存)

        这种方式允许将需要缓存的信息包含在一个用户控件内,然后,将该用户控件标记为可缓存的,以此来缓存页面输出的部分内容。该选项允许缓存页面中的特定内容,而没有缓存整个页面,因此,每次都需重新创建整个页。例如,如果要创建一个显示大量动态内容(如股票信息)的页,其中有些部分为静态内容(如每周总结),这时可以将静态部分放在用户控件中,并允许缓存这些内容。

        在ASP.NET中,提供了UserControl这种用户控件的功能。一个页面可以通过多个UserControl来组成。只需要在某个或某几个UserControl里设置缓存。

        例如:

        那么可以在WebUserControl1.ascx的页头代码中添加声明语句:

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs"
        Inherits="WebApplication1.WebUserControl1" %>
    <%@ OutputCache Duration="60" VaryByParam="none" %>
    <%=DateTime.Now %>

      调用该控件的页面default.aspx代码:

    隐藏行号 复制代码
    1. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
      
    2. 
      
    3. <%@ Register Src="WebUserControl1.ascx" TagName="WebUserControl1" TagPrefix="uc1" %>
      
    4. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      
    5. <html xmlns="http://www.w3.org/1999/xhtml">
      
    6. <head runat="server">
      
    7.     <title></title>
      
    8. </head>
      
    9. <body>
      
    10.     <form id="form1" runat="server">
      
    11.     <br />
      
    12.     <%=DateTime.Now %>
      
    13.     <br />
      
    14.     <uc1:WebUserControl1 ID="WebUserControl11" runat="server" />
      
    15.     </form>
      
    16. </body>
      
    17. </html>
      
    18. 
      

    这时候刷新WebForm1.aspx页面时,页面的时间每次刷新都变化,而用户控件中的时间数据却是60秒才变化一次,说明对页面的“局部”控件实现了缓存,而整个页面不受影响。

     

    2. 缓存后替换

         与控件缓存正好相反。它对整个页面进行缓存,但是页中的某些片段是动态的,因此不会缓存这些片段。ASP.NET页面中既包含静态内容,又包含基于数据库数据的动态内容。静态内容通常不会发生变化。因此,对静态内容实现数据缓存是非常必要的。然而,那些基于数据的动态内容,则不同。数据库中的数据可能每时每刻都发生变化,因此,如果对动态内容也实现缓存,可能造成数据不能及时更新的问题。对此问题如果使用前文所述的控件缓存方法,显然不切实际,而且实现起来很繁琐,易于发生错误。

     

         如何实现缓存页面的大部分内容,而不缓存页面中的局部某些片段。ASP.NET 2.0提供了缓存后替换功能。实现该项功能可通过以下三种方法:

        一是以声明方式使用Substitution控件,

        二是以编程方式使用Substitution控件API,

        三是以隐式方式使用控件。

        前两种方法的核心是Substitution控件,本节将重点介绍该控件,第三种方法仅专注于控件内置支持的缓存后替换功能,本节仅做简要说明。

     

    (1) Substitution控件应用

         为提高应用程序性能,可能会缓存整个ASP.NET页面,同时,可能需要根据每个请求来更新页面上特定的部分。例如,可能要缓存页面的很大一部分,需要动态更新该页上与时间或者用户高度相关的信息。在这种情况下,推荐使用Substitution控件。Substitution控件能够指定页面输出缓存中需要以动态内容替换该控件的部分,即允许对整页面进行输出缓存,然后,使用Substitution控件指定页中免于缓存的部分。需要缓存的区域只执行一次,然后从缓存读取,直至该缓存项到期或被清除。动态区域,也就是Substitution控件指定的部分,在每次请求页面时都执行。Substitution控件提供了一种缓存部分页面的简化解决方案。

    隐藏行号 复制代码
    1. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
      
    2. 
      
    3. <%@ OutputCache Duration="60" VaryByParam="none" %>
      
    4. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      
    5. <html xmlns="http://www.w3.org/1999/xhtml">
      
    6. <head runat="server">
      
    7.     <title></title>
      
    8. </head>
      
    9. <body>
      
    10.     <form id="form1" runat="server">
      
    11.     <br />
      
    12.     页面缓存的时间:<%= DateTime.Now.ToString() %>
      
    13.     <br />
      
    14.     真实(替换)的时间:<asp:Substitution ID="Substitution1" runat="server" MethodName="getCurrentTime" />
      
    15.     </form>
      
    16. </body>
      
    17. </html>
      
    18. 
      

    页面后台代码:

    隐藏行号 复制代码
    1. public static string getCurrentTime(HttpContext context)
      
    2. {
      
    3.     return DateTime.Now.ToString();
      
    4. }
      

    如上代码所示,Substitution控件有一个重要属性:MethodName。该属性用于获取或者设置当Substitution控件执行时为回调而调用的方法名称。该方法比较特殊,必须符合以下3条标准:

        1)   此方法必须被定义为静态方法;

        2)   此方法必须接受HttpContext类型的参数;

        3)   此方法必须返回String类型的值。

     

         在运行情况下,Substitution控件将自动调用MethodName属性所定义的方法。该方法返回的字符串即为要在页面中的Substitution控件的位置上显示的内容。如果页面设置了缓存全部输出,那么在第一次请求时,该页将运行并缓存其输出。对于后续的请求,将通过缓存来完成,该页上的其他代码不会再运行。但Substitution控件及其有关方法则在每次请求时都执行,并且自动更新该控件所表示的动态内容,这样就实现了整体缓存,局部变化的替换效果。

     

         如上代码所示,在代码头部通过@ OutputCache指令设置页面输出缓存过期时间为5秒,这意味着整个页面数据都应用了缓存功能。因此,“页面缓存的时间”所显示的时间值来自于数据缓存。这个时间值不会随着刷新页面而变化,仅当缓存过期时才会发生更新。Substitution控件的MethodName属性值为getCurrentTime。该控件显示的内容来自于getCurrentTime方法的返回值。尤为重要的是,虽然页面设置了输出缓存功能,但是每当页面刷新时,ASP.NET执行引擎仍然要重新执行Substitution控件,并将MethodName属性值指定的方法返回值显示在页面上,因此,显示的是当前最新时间。

    随着页面的刷新,真实时间在变,而页面缓存的时间在指定的缓存时间内始终不变。

    注意:

    1)   Substitution控件无法访问页上的其他控件,也就是说,无法检查或更改其他控件的值。但是,代码确实可以使用传递给它的参数来访问当前页上下文。

    2)   在缓存页包含的用户控件中可以包含Substitution控件。但是,在输出缓存用户控件中不能放置Substitution控件。

    3)    Substitution控件不会呈现任何标记,其位置所显示内容完全取决于所定义方法的返回字符串。

    (2) Substitution控件API应用

     

    上一小节介绍了以声明方式使用Substitution控件实现缓存后替换的应用。本节说明另一种实现方法。该方法的核心是以编程方式利用Substitution控件API实现缓存后替换,相对于以声明方式使用Substitution控件的方法具有更强灵活性。

     

    通过为Substitution指定回调方法,实现和声明同样的效果。Substitution的回调方法必须是

    HttpResponseSubstitutionCallback委托定义的方法,它有两个特征:

    1)  一是返回值必须是String,

    2)   二是参数有且仅有一个,并且是HttpContext类型。

     

    当需要以编程方式,为缓存的输出响应动态生成指定的响应区域时,可以在页面代码中将某个方法(即回调方法)的名称作为参数(HttpResponseSubstitutionCallback)传递给Substitution。这样Substitution就能够使用回调方法,并将回调方法的返回值作为给定位置的替代内容显示出来。

     

    需要注意的是,回调方法必须是线程安全的,可以是作为容器的页面或者用户控件中的静态方法,也可以是其他任意对象上的静态方法或实例方法。

     

    下面演示一个以编程方式将 Substitution 控件添加到输出缓存网页。与(1)Substitution控件应用所示的示例完成同样功能。不同的是实现方式。

    隐藏行号 复制代码
    1. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
      
    2. 
      
    3. <%@ OutputCache Duration="60" VaryByParam="none" %>
      
    4. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      
    5. <html xmlns="http://www.w3.org/1999/xhtml">
      
    6. <head runat="server">
      
    7.     <title></title>
      
    8. </head>
      
    9. <body>
      
    10.     <form id="form1" runat="server">
      
    11.     <div>
      
    12.         页面缓存的时间:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
      
    13.     </div>
      
    14.     <div>
      
    15.         真实(缓存替换)的时间:
      
    16.         <asp:PlaceHolder ID="PlaceHolder1" runat="Server"></asp:PlaceHolder>
      
    17.     </div>
      
    18.     </form>
      
    19. </body>
      
    20. </html>
      
    21. 
      

    页面后台CS代码:

    隐藏行号 复制代码
    1. protected void Page_Load(object sender, EventArgs e)
      
    2. {
      
    3.     //创建一个Substitution
      
    4.     Substitution Substitution1 = new Substitution();
      
    5. 
      
    6.     //指定调用的回调方法名
      
    7.     Substitution1.MethodName = "GetCurrentDateTime";
      
    8. 
      
    9.     PlaceHolder1.Controls.Add(Substitution1);
      
    10.     Label1.Text = DateTime.Now.ToString();    
      
    11. }
      
    12. 
      
    13. public static string getCurrentTime(HttpContext context)
      
    14. {
      
    15.     return DateTime.Now.ToString();
      
    16. }
      

      如上代码所示,页面使用@ OutputCache指令设置了输出缓存功能,其配置数据缓存过期时间为60秒。然而,页面其他内容都被缓存,通过Substitution调用的回调方法显示的内容是不被缓存的。

  • 相关阅读:
    ionic localstorage
    angular 中文鏈接
    把jqmobi 變成jQuery 的插件 從此使用jQuery
    jqmobi 的一些設置
    ionic ngcordova map 地圖
    ionic pull to refresh 下拉更新頁面
    json 對象的序列化
    鍵盤彈出,頁面佈局被推上去了.....
    Cordova V3.0.0中config.xml配置文件的iOS Configuration
    android ios 只能輸入數字 不能輸入小數點的 函數 cordova
  • 原文地址:https://www.cnblogs.com/jx270/p/4212254.html
Copyright © 2011-2022 走看看