优化网站设计(三):对资源添加缓存控制

前言

网站设计的优化是一个很大的话题,有一些通用的原则,也有针对不一样开发平台的一些建议。这方面的研究一直没有中止过,我在不一样的场合也分享过这样的话题。html

做为通用的原则,雅虎的工程师团队曾经给出过35个最佳实践。这个列表请参考web

Best Practices for Speeding Up Your Web Site  http://developer.yahoo.com/performance/rules.html

同时,他们还发布了一个相应的测试工具Yslow http://developer.yahoo.com/yslow/chrome

我强烈推荐全部的网站开发人员都应该学习这些最佳实践,并结合本身的实际项目状况进行应用。api

接下来的一段时间,我将结合ASP.NET这个开发平台,针对这些原则,经过一个系列文章的形式,作些讲解和演绎,以帮助你们更好地理解这些原则,而且更好地使用他们。浏览器

准备工做

为了跟随我进行后续的学习,你须要准备以下的开发环境和工具缓存

  1. Google Chrome 或者firefox ,而且安装 Yslow这个扩展组件.请注意,这个组件是雅虎提供的,但目前没有针对IE的版本。
    1. https://chrome.google.com/webstore/detail/yslow/ninejjcohidippngpapiilnmkgllmakh
    2. https://addons.mozilla.org/en-US/firefox/addon/yslow/
    3. 你应该对这些浏览器的开发人员工具备所了解,你能够经过按下F12键调出这个工具。
  2. Visaul Studio 2010 SP1 或更高版本,推荐使用Visual Studio 2012
    1. http://www.microsoft.com/visualstudio/eng/downloads
  3. 你须要对ASP.NET的开发基本流程和核心技术有至关的了解,本系列文章很难对基础知识作普及。

本文要讨论的话题

缓存!这是一条多么重要的原则。几乎全部的网站优化的书籍或者文章中都会提到这个原则,并且目前在运行的一些网站都或多或少地使用到了这个技术。这个原则的相关概念能够参考这里:http://developer.yahoo.com/performance/rules.html#expires 服务器

咱们仍是以博客园的主页为例,经过简单的监控就能发现,他们大量地使用了缓存的功能(针对不一样资源,缓存的策略可能略有不一样,请注意观察max-age的值,以秒为单位,有兴趣的同窗能够计算一下)工具

image

 

接下来,我会从几个方面,和你们来谈谈缓存的问题性能

1.缓存的概念

缓存是服务器与客户端(或者中间的代理服务器)之间的一种约定,利用缓存能够明显地减小重复从服务器下载内容的次数,这样就能够极大地提升吞吐量以及响应速度。在HTTP 1.1协议中,对于缓存有明确的,详细的说明:http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html学习

因为缓存如此重要,因此对于不少浏览器而言(尤为是现代浏览器),他们默认就会尝试对静态内容进行缓存。(这里先卖一个关子,你们以为默认状况下它会缓存多长时间呢?)

下图能够很好地揭示缓存的做用

image

这是我两次访问一个简单的页面的情形,第一次(我用颜色选中的8个请求)的时候,由于没有缓存,因此全部的内容资源(动态的和静态的)都须要下载。浏览器会根据状况对其进行缓存(一般就是对于静态内容它会有一个缓存的策略,后面再细述)。可是第二次访问,就彻底不同了,只有第1个请求是须要下载内容的(这是一个动态页面),其余的7个内容都是无需下载的(你能够看到状态码是304,并且Body都是0)

 

2.静态资源的缓存及其设置

默认状况下,浏览器(至少绝大多数现代浏览器)都会对网站中的静态内容进行缓存。常见的静态内容包括

  1. HTM,HTML文件
  2. JAVASCRIPT文件
  3. CSS文件
  4. 图片文件

若是服务器端不作任何的设置,那么默认状况下它缓存多长时间呢?答案是:可能好久,这个取决于两个因素

  1. 浏览器缓存中的这个文件是否被清理(多是用户手工地进行清理,有的公司也可能会设置统一的策略自动在浏览器关闭的时候清理)
  2. 服务器对应的文件是否有更新

这里就要讲到那个304的状态码了. 这个状态码的意思是:Not Modified(未更改)。为何会产生这样的状态码呢?其实能够经过下面三个截图来理解清楚

第一次请求某静态资源的时候,服务器会在返回内容(状态码为200)的同时,包含一个特殊的Header,叫作Last-Modified ,这个Header会记录在服务器端该文件最后修改的时间。以下图所示

image

而后,浏览器会将此文件缓存起来。

接下来若是须要第二次访问这个文件,浏览器发起的请求中,也会包含一个特殊的Header

image
这个Header的意思是说,要检查从这个时间后是否有修改。若是该文件没有修改过,则服务器就会返回304这个状态码,而且不会返回任何内容。

image

浏览器收到了304这个状态码的话,就会使用本身已经缓存的那个版本进行呈现。

咱们固然也能够静态资源的缓存策略进行人工的干预,这个能够经过两个途径来实现

  1. 经过IIS 管理界面。选择某个站点,而后在右侧的功能面板中,选择“Http Response Header”,以下图所示

image

而后在功能页面中,点击右侧的“Set Common Header…” 这个Action

image

而后在弹出的对话框中设置Expire Web Content的选项

image

这里默认会有三个策略:当即过时,在一个相对时间范围内过时,在一个绝对时间后过时。你能够根据本身的需求进行设置。

【备注】这些设置仅仅影响静态资源。

  1. 直接修改web.config文件

上面提到的经过IIS管理界面对静态资源配置到期时间(其实也就是指一个缓存的时间),这个作法适合给管理员使用。做为开发人员,若是你但愿本身来控制这些选项,那么能够直接在网站的配置文件(web.config)中添加相关的配置便可。

 <system.webServer>
        <staticContent>
            <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00" />
        </staticContent>
    </system.webServer>

 

须要注意的是,在以前的截图中,有些特殊的脚本,它们的缓存时间是不受这个配置影响的。

image

他们是默认缓存一年的.这些特殊的脚本(或者样式表)实际上是多个文件的组合,若是对这一点不太了解,请参考我以前的一篇文章

优化网站设计(一):减小请求数

3.动态资源的缓存及其设置

咱们上面讨论到了静态资源的缓存及其设置,可是对于如今的大部分网站来讲,光有静态资源是远远不够的,咱们会有不少动态资源,典型的就是动态页面(例如aspx页面),那么对于这种动态资源,是否也有可能进行必定的缓存呢?

答案是确定的,但对于动态资源的缓存细节至关多,恐怕要超出本文的范畴。我强烈推荐你们详细阅读MSDN中的这篇文档 :

http://msdn.microsoft.com/en-us/library/aa478965.aspx (ASP.NET Caching: Techniques and Best Practices)

 

我这里为你们总结一下对动态资源进行缓存的几种作法

  1. 页面缓存,在页面中使用OutputCache,适合于对整个页面全部内容作缓存
  2. 片断缓存,在用户控件中使用OutputCache,适合于对页面的一部分(一般封装为一个用户控件)内容作缓存
    • 在MVC中,一样能够在Action上面使用OutputCache这个Attribute来定义缓存设置
  3. 数据缓存,在代码中访问Cache对象,适合对多个页面中可能会用到的共享数据作精细的缓存控制

值得注意的是,这三种作法并不是是互斥的,在实际的应用中,他们会相互结合起来使用。

 

另外,除了给页面或者控件设置OutputCache(为了灵活起见,建议结合CacheProfile)以外,若是确实某些缓存的设置须要动态决定,也能够采用以下的方式来实现一样的效果

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(false);
Response.Cache.VaryByParams["Category"] = true;

if (Response.Cache.VaryByParams["Category"])
{
   //...
}

关于Response.Cache的全部属性和操做,有兴趣的能够参考 http://msdn.microsoft.com/EN-US/library/system.web.httpcachepolicy.aspx

【备注】本文以前提到的Bundle默认设置为1年的过时时间就是经过这种方式来实现的。

 

 

4.缓存的反面

缓存是一种颇有用的技术,几乎全部人都知道它的好处。如今的开发平台都比较强大,让咱们能够有比较简单的方式来实现缓存。

可是,缓存有它的一些代价,或者说有反面的一些问题须要考虑。典型的问题在于

  1.  版本控制
  2. 容量问题
    • 静态资源一般是缓存在客户端的(除非服务器端作特殊设置,IIS 7开始支持在服务器端——甚至内核模式——中缓存内容),他们一般对服务器影响不大。
    • 但动态资源的缓存,一般是缓存在服务器端的(或者客户端和服务器端各有一份),因此须要占用服务器的内存空间。
    • 若是不加以限制(或者不作周全的考虑),则极可能会由于缓存了过多的内容,而致使服务器的内存出现争用的问题。
      • 这里留一个问题,请问ASP.NET应用程序的缓存功能,默认最多可使用多少服务器内存?
    • 这里所谓的周全考虑,是指咱们须要对缓存的必要性进行评估。应该只缓存那些确实有必要缓存的内容。这个说来容易,实际上作起来倒是不那么容易的。
相关文章
相关标签/搜索