ASP.NET MVC缓存

根据缓存的位置不同,可以区分为:

  ①客户端缓存(缓存在用户的客户端,例如浏览器中)

  ②服务器缓存(缓存在服务器中,可以缓存在内存中,也可以缓存在文件里,并且还可以进一步地区分为本地缓存和分布式缓存两种)

  应该说,缓存的设计是一门较为复杂的学问,主要考虑的问题包括:要不要缓存?要缓存哪些数据?要缓存多少数据?要缓存多久?如何更新缓存(手动还是自动)?将缓存放在哪里?本文将以较为通俗易懂的方式,来看一看在MVC4的项目中,如何使用缓存功能。对于上述提到的一些具体业务问题,我这里不会进行太过深入地探讨。

MVC3中的缓存功能

  ASP.NET MVC3 继承了ASP.NET的优良传统,内置提供了缓存功能支持。主要表现为如下几个方面:

  ①可以直接在Controller,Action或者ChildAction上面定义输出缓存(这个做法相当于原先的页面缓存和控件缓存功能)

  ②支持通过CacheProfile的方式,灵活定义缓存的设置(新功能)

  ③支持缓存依赖,以便当外部资源发生变化时得到通知,并且更新缓存

  ④支持使用缓存API,还支持一些第三方的缓存方案(例如分布式缓存)

  那么,下面我们就逐一来了解一下

一、使用输出缓存

MVC中内置了一个OutputCache的ActionFilter,我们可以将它应用在某个Action或者ChildAction上面

【备注】ChildAction是MVC3的一个新概念,本质上就是一个Action,但通常都是返回一个PartialView。通常这类Action,可以加上一个ChildActionOnly的ActionFilter以标识它只能作为Child被请求,而不能直接通过地址请求。

【备注】我们确实可以在Controller级别定义输出缓存,但我不建议这么做。缓存是要经过考虑的,而不是不管三七二十一就全部缓存起来。缓存不当所造成的问题可能比没有缓存还要大。

1 [OutputCache(Duration=10)]
2         public ActionResult Index()
3         {
4             //这里目前作为演示,是直接硬编码,实际上可能是读取数据库的数据
5             var employees = new[]{
6                 new Employee(){ID=1,Name="ares",Gender="Male"}
7             };
8             return View(employees);
9         }

   那么,也就是说,第一次请求这个Index的时候,里面的代码会执行,并且结果会被缓存起来,然后在10秒钟内,第二个或者后续的请求,就不需要再次执行,而是直接将结果返回给用户即可。

  这个OutputCache的Attribute,实际上是一个ActionFilter,它有很多参数。参考http://msdn.microsoft.com/zh-cn/library/system.web.mvc.outputcacheattribute(v=vs.118).aspx

使用缓存配置文件

  第一节中,我们详细地了解了MVC中,如何通过OutputCache这个ActionFilter来设置缓存。但是,因为这些设置都是通过C#代码直接定义在Action上面的,所以未免不是很灵活,例如我们可能需要经常调整这些设置,该如何办呢?

  ASP.NET 4.0中提供了一个新的机制,就是CacheProfile的功能,我们可以在配置文件中,定义所谓的Profile,然后在OutputCache这个Attribute里面可以直接使用。

  通过下面的例子,可以很容易看到这种机制的好处。下面的节点定义在system.web中

1 <caching>
2       <outputCacheSettings>
3         <outputCacheProfiles>
4           <add name="employee" duration="10" enabled="true" location="ServerAndClient" varyByParam="none"/>
5         </outputCacheProfiles>
6       </outputCacheSettings>
7     </caching>
 1 [OutputCache(CacheProfile="employee")]
 2         public ActionResult Index()
 3         {
 4             //Response.Cache.SetOmitVaryStar(true);
 5             ViewBag.CurrentTime = DateTime.Now.ToString();
 6 
 7             //这里目前作为演示,是直接硬编码,实际上可能是读取数据库的数据
 8             var employees = new[]{
 9                 new Employee(){ID=1,Name="ares",Gender="Male"}
10             };
11             return View(employees);
12         }

 

 二、使用缓存API

  通过上面的两步,我们了解到了使用OutputCache,并且结合CacheProfile,可以很好地实现灵活的缓存配置。但是有的时候,我们可能还希望对缓存控制得更加精细一些。因为OutputCache是对Action的缓存,不同的Action之间是不能共享数据的,假如某些数据,我们是在不同的Action之间共享的,那么,简单地采用OutputCache来做,就会导致对同一份数据,缓存多次的问题。

  所以,ASP.NET除了提供OutputCache这种基于声明的输出缓存设置之外,还允许我们在代码中,自己控制要对哪些数据进行缓存,并且提供了更多的选项。

  关于如何通过API的方式添加或者使用缓存,请参考http://msdn.microsoft.com/zh-cn/library/18c1wd61%28v=VS.80%29.aspx

  基本上就是使用HttpContext.Cache类型,可以完成所有的操作,而且足够灵活。

  值得一提的是,我知道不少公司在项目中都会采用一些ORM框架,某些ORM框架中也允许实现缓存。例如NHibernate就提供了较为丰富的缓存功能,大致可以参考一下 http://www.cnblogs.com/RicCC/archive/2009/12/28/nhibernate-cache-internals.html

  需要注意的是,微软自己提供的Entity Framework本身并没有包含缓存的功能。

  这里仍然要特别提醒一下,使用这种基于API的缓存方案,需要仔细推敲每一层缓存的设置是否合理,以及更新等问题。

三、使用缓存依赖

  很早之前,在ASP.NET中设计缓存的时候,我们就可以使用缓存依赖的技术。关于缓存依赖,详细的信息请参考 http://msdn.microsoft.com/zh-cn/library/ms178604.aspx

  实际上,这个技术确实很有用,ASP.NET默认提供了一个SqlCacheDependency,可以通过配置,连接SQL Server数据库,当数据库的表发生变化的时候,会通知到ASP.NET,该缓存就会失效。

  值得一提的是,不管是采用OutputCache这样的声明式的缓存方式,还是采用缓存API的方式,都可以使用到缓存依赖。而且使用缓存API的话,除了使用SqlCacheDependency之外,还可以使用标准的CacheDependency对象,实现对文件的依赖。

四、分布式缓存

  上面提到的手段都很不错,如果应用系统不是很庞大的话,也够用了。需要注意的是,上面所提到的缓存手段,都是在Web服务器本地内存中进行缓存,这种做法的问题在于,如果我们需要做负载均衡(一般就会有多台服务器)的时候,就不可能在多台服务器之间共享到这些缓存。正因为如此,分布式缓存的概念就应运而生了。

  谈到分布式缓存,目前比较受到大家认可的一个开源框架是 memcached。顾名思义,它仍然使用的是内存的缓存,只不过,它天生就是基于分布式的,它的访问都是直接通过tcp的方式,所以可以访问远程服务器,也可以多台Web服务器访问同一台缓存服务器。

  需要注意的是,分布式缓存不是为了来提高性能的(这可能是一个误区),并且可以肯定的是,它的速度一定会被本地慢一些。如果你的应用只有一台服务器就能满足要求,你就没有必要使用memcached。它的最大好处就是跨服务器,跨应用共享缓存。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。