缓存(Cache)
什么是缓存?
web应用程序可被多个用户访问。当用户少,负载低时,可提供快速的访问。当负载成倍增加时,响应就慢下来了。服务器响应慢是高负载网站最常见的问题。为了解决这个问题,我们常采用升级硬件配置,负载均衡,增加带宽等措施。但下载并不是响应慢的唯一原因。我们需要提供一种加快数据访问的机制,进而提升网站的性能。缓存提供了这种解决方案。
缓存是种技术。我们可以把频繁使用的数据缓存或把网页临时缓存在本地硬盘为了以后再次访问。在大量用户访问一个站点或一个用户多次访问站点时,缓存技术能加快响应。缓存可以出现在客户端(浏览器缓存),或者在服务器与客户端之间(代理缓存/倒置代理缓存),或者在服务器(页面缓存/数据缓存)。
经常我们选择在web服务器缓存数据,它虽然提高了性能,但并不是每次都能解决我们的问题。当我们缓存数据时,需要考虑缓存的位置。
缓存位置:
我们归纳为4个缓存位置:
1. 客户端缓存(Client Caching)
2. 代理缓存(Proxy Caching)
3. 倒置代理缓存(Reverse Proxy Caching)
4. Web服务器缓存(Web Server Caching)
1.客户端缓存 :
客户端浏览器把数据缓存为临时文件保存在本地硬盘,或者缓存数据在客户端内存种。通过客户端缓存减少了网络和服务器的负载从而提供了快速的访问。信息不能被别的客户端共享,所以信息是客户端专有。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/client_caching.jpg)
优点:
1. 缓存在客户端的数据易于被访问
2. 减少了网络和服务器的负载
缺点:
1. 缓存数据依赖于浏览器,不可共享
2. 代理缓存 :
客户端缓存的主要缺点是:数据缓存在客户端,客户端专有。代理缓存技术使用专有的服务器存储缓存数据。它位于客户端和web服务器之间可共享的位置,所以所有的客户端可以使用相同的共享数据。代理服务器处理所有的网页请求,并不发送请求到网络另一段的实际web服务器。从而加快了访问。
代理缓存服务器常放在网关附近以减少带宽。大量客户端时,经常多个代理缓存服务器,被成为缓存组。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/proxy_caching.jpg)
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/cache_array.jpg)
优点:
1. 缓存在代理服务器的数据易于访问
2. 减少了网络流量
缺点:
1.代理缓存服务器的部署、维护需要一定的成本
3. 倒置代理缓存:
一些代理缓存服务器被放置在web服务器前,减少web服务器接受的请求数。这容许代理服务器直接响应频繁的请求,而把别的请求返回给web服务器。这就叫做倒置代理缓存。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/Reverse_Proxy_Caching.jpg)
优点:
1. 缓存的数据易于访问。
2. 减少了web服务器请求数量。
缺点:
1. 因为代理服务器配置在web服务器前,有时会增加网络流量。
4. web服务器缓存 :
数据被缓存在web服务器上。数据缓存和页面缓存是常用的缓存机制。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/Web_Server_Caching.jpg)
优点:
1. 减少了数据从数据库或其它服务器到web服务器的往返,提高了站点的性能。
缺点:
1. 增加了网络负载
ASP.NET中的缓存
ASP.NET 支持页面缓存,局部页面缓存,数据缓存。缓存页面是动态产生的,被叫做页面输出缓存。在页面缓存机制中,仅当页面第一次被访问时,页面被自动缓存。随后访问相同页面直接从缓存获得。ASP.NET也允许缓存页面局部,叫做局部页面缓存或片段缓存。另外被缓存的服务器数据(数据库数据,xml数据),很容易从缓存获得,而不用重新检索,缓存减少了从数据库或其它数据源往返的次数。ASP.NET提供完整功能的数据缓存引擎。完全支持清除,到期和文件、时间、键依赖机制。在ASP.NET程序中,有两个缓存的位置被用来促进网站的性能。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/Caching_Opportunity_in_ASP.NET.jpg)
在上图中 (1) 被用来返回页面输出缓存 (2) 使用数据缓存减少数据往返。
不同类型的缓存
1 . 页面输出缓存 :
在开始页面输出缓冲前,让我们先了解一下页面的编译过程。aspx页编译有两个阶段。首先,代码编译成微软中间语言( MSIL )代码。然后,在执行过程时中间语言代码被JIT编译为本地代码。当我们构建网站时,在ASP.NET网页编译整个代码被编译MSIL。但在执行时,根据用户的请求,只有部分MSIL代码被编译为本地代码,这提高性能。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/Page_Execution.jpg)
只要页面有变化,每次请求时就需要JIT编译。所以我们可以使用页面输出缓存,缓存那些相对静态的内容,而不用每次用户请求时生成页面。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/Page_Output_caching.jpg)
从上图可以看出,第一次请求页面被生成、缓存。再请求相同的页面从缓存中取得,不用重新生成该页面。
为了实现页面输出缓存,在ASP.NET页面中,加OutputCache指令,指定Duration(以秒为单位)。
- <%@ Page Language="C#" %>
- <%@ OutputCache Duration='300' VaryByParam='none' %>
- <html>
- <script runat="server">
- protected void Page_Load(Object sender, EventArgs e) {
- lbl_msg.Text = DateTime.Now.ToString();
- }
- </script>
- <body>
- <h3>Output Cache example</h3>
- <p>Page generated on:
- <asp:label id="lbl_msg" runat="server"/></p>
- </body>
- </html>
也可以在后台代码中指定缓存属性:
- void Page_Load(Object sender, EventArgs e) {
- Response.Cache.SetExpires(DateTime.Now.AddSeconds(360));
- Response.Cache.SetCacheability(
- HttpCacheability.Public);
- Response.Cache.SetSlidingExpiration(true);
- _msg.Text = DateTime.Now.ToString();
- }
自此提一下Duration和VaryByParam属性。Duration指定缓存持久的时间。VaryByParam表示每当参数改变就缓存。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/Varyparam_Cached.jpg)
如上图显示,如果我们使用查询参数请求页面,根据查询参数缓存页面,这里需要用到outputcache的VaryByParam属性。根据查询缓存页面,当用户再次带这些参数请求页面时,就可以从缓存中取得。下面的例子详细的显示了VaryByParam属性的用法。
- <%@ OutputCache Duration="60" VaryByParam="*" %>
- //页面将缓存60秒, 页面为每个querystring参数生成一个独立的缓存。
下面的表显示了outputcache最常用、最重要的属性。
属性 | 值 | 描述 |
---|---|---|
Duration | Number | 定义页面将缓存多长时间 (秒) |
Location | 'Any'
'Client' 'Downstream' 'Server' 'None' |
定义页面缓存的位置 |
VaryByCustom | 'Browser' | 根据浏览器名字和版本和自定义字符改变输出缓存 |
VaryByParam | 'none' '*' | 这是一个必要的属性,指定页面查询字符串。这是我已经讨论过 |
OutputCache指令所有的属性填充System.Web.HttpCachePolicy类的实例。ASP.NET提供的完整的缓存实现策略被封装在HttpCachePolicy中。
输出缓存的位置
我们已经提到可以缓存数据在客户端,服务器或客户端和服务器之间。现在我将讨论可行的设置缓存位置。
除了在页面绘制时可以缓存数据外,我们缓存数据在客户端浏览器来减少网络流量。 OutputCache指令可可以指定三种类型的缓存:服务器,客户端和代理(默认);
下面的表是位置的明细。它显示了缓存位置,对HTTP消息头Cache-Control和Expires影响.
位置值 | Cache-Control头 | Expires头 | 在服务器缓存 | 描述 |
---|---|---|---|---|
'Any' | public | Yes | Yes | Page can be cached on the browser client, a downstream server, or the server |
'Client' | private | Yes | No | Page will be cached on the client browser only. |
'Downstream' | public | Yes | No | Page will be cached on a downstream server and the client |
'Server' | no-cache | No | Yes | Page will be cached on the server only. |
'None' | no-cache | No | No | Disables output caching for this page. |
例如:如果你在页面指定OutputCache指令的Location属性值是'Client',那么这个页面不会被缓存在服务器上。但是响应中将包含Cache-Control消息头(指定是否应该缓存在代理上)和Expires消息头(指定过多久该从服务器上重新取数据). Cache-Control的值是Private。Expires的值是Duration指定的时间戳。
- <%@ OutputCache Duration='120' Location='Client' VaryByParam='none' %>
表示缓存120秒,数据不保存在服务器,保存在客户端浏览器。
2 .页面片段缓存: ASP.NET提供了缓存局部页面的机制。为了缓存局部页面,首先你应该把需要缓存的局部封装到用户控件,在用户控件的文件上加指定了Duration和VaryByParam属性的OutputCache。当用户控件在运行时载入时,它就被缓存了,所有包含了这个用户控件的页面被后来请求时,将从缓存获得该控件。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/Fragment_Cached.jpg)
- <!— UserControl.ascx —>
- <%@ OutputCache Duration='60'
- VaryByParam='none' %>
- <%@ Control Language="'C#'" %>
- <script runat="server">
- protected void Page_Load(Object src, EventArgs e)
- {
- _date.Text = "User control generated at " +
- DateTime.Now.ToString();
- }
- </script>
- <asp:Label id='_date' runat="'server'" />
这里我在用户控件中使用了缓存,每当我们请求页面时,局部页面将被缓存。
3.数据缓存:数据缓存可以大幅度提高应用程序的性能,减少数据库的访问和数据往返开销。简单的数据缓存存储请求的数据在缓存中,web服务器不用每次发送请求到数据库服务器,这提高了web服务器的性能。被缓存的应该是被所有人访问的通用数据。数据缓存是一个全功能的高速缓存引擎,使您能够存储和检索在同一应用程序多个HTTP请求和多个会话的数据。
![](http://www.it118.org/UserFiles/Image/321869dd-98cb-431b-b6d2-82d973cd739d/datacaching.png)
上图显示如何直接从数据库直接访问数据,又如何从缓存中获取数据。数据缓存并不仅仅和SQL Server相关,它也能存储其它数据源的数据。
下来看看怎么在web应用程序中实现数据缓存。有3中不同的方式把数据加入到缓存中,根据情况对其访问。这些方法是 Cache[], Cache.add(), cache.insert()。下表清楚的显示了这些方法不同点。