我爱电脑技术论坛's Archiver

白雪公主 发表于 2008-3-30 09:19

缓存技术及在Rainbow Portal的应用

 1. ASP.NET缓存技术概述 H(K1t%Aqb.wu'w

:R7{z#O,C   将数据库中的数据缓存到内存(也可以存储在其他场所),则无需在请求每个页面时都访问数据库。由于从内存中返回数据的速度始终比新提供的数据速度快,因而可以大大提高应用程序的性能。yI'~;X6i^/ZU }5s
0bFU"v2l~#d:F
  ASP.NET为你使用缓存技术提供最大的灵活性,你可以缓存整个HTML页面,或是部分HTML页面,或是各种对象。你可以设置过期策略,或是设置依赖性,即在其他资源如文件或数据库表改变时,自动移出缓存。
S-lR/@$YW!~$g} T*^-DX'c*L%{
  ASP.NET中有两种基本的缓存:}.j F&c2M!CY$dv

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

\giM?wend   可以通过在Web.config进行配置,设置缓存策略,在一组ASP.net页面中使用。还可以通过HttpCachePolicy类编程性设置页面缓存。
0h0SO]5SK8G X;MZ2}0f:B[
  数据缓存
r9b8Y N c0zZ+E
1f"_$o2X+Q5b6@e   应用程序数据缓存提供了一种编程方式,可通过键/值对将任意数据存储在内存中。使用应用程序缓存与使用应用程序状态类似。但是,与应用程序状态不同的是,应用程序数据缓存中的数据是易失的,即数据并不是在整个应用程序生命周期中都存储在内存中。应用程序数据缓存的优点是由ASP.NET管理缓存,它会在项过期、无效,或内存不足时移除缓存中的项,还可以配置应用程序缓存,以便在移除项时通知应用程序。R4y5W1Q%_(W7lhE

5QEEO0g*w*T8Mt   同时还有两种特殊的缓存,基于以上的缓存模型:
W+{/S6kpO-iJ 7e DR`m&\
  部分缓存
/X9G3N~I%zU+Ll 9]|5v\;tD2]@
  部分缓存本质上是输出缓存。顾名思义,页面部分缓存是将页面部分内容保存在内存中以便响应用户请求,而页面其他部分内容则为动态内容。页面部分缓存的实现包括两种方式:控件缓存和替换后缓存。前者也可称为片段缓存,这种方式允许将需要缓存的信息包含在一个用户控件内,然后,将该用户控件标记为可缓存的,以此来缓存页面输出的部分内容。这一方式缓存了页面中的特定内容,而没有缓存整个页面,因此,每次都需重新创建整个页。例如,如果要创建一个显示大量动态内容(如股票信息)的页,其中有些部分为静态内容(如每周总结),这时可以将静态部分放在用户控件中,并允许缓存这些内容。缓存后替换与控件缓存正好相反。这种方式缓存整个页,但页中的各段都是动态的。例如,如果要创建一个在规定时间段内为静态的页,则可以将整个页设置为进行缓存。如果向页添加一个显示用户名的Label控件,则对于每次页刷新和每个用户而言,Label的内容都将保持不变,始终显示缓存该页之前请求该页的用户的姓名。使用缓存后替换机制,可以将页配置为进行缓存,将页的个别部分标记为不可缓存。在此情况下,可以向不可缓存部分添加Label控件,这样将为每个用户和每次页请求动态创建这些控件。
b&ZzR/CE )i9X,Z1jL']2e zwE)|
  数据源缓存Rk$N!@!} l
3rS!di]z u#r
  数据源缓存是指在数据源控件如SqlDataSource, ObjectDataSource, and XmlDataSource中缓存数据,实际上是数据缓存,只不过缓存由控件内部实现。
a:v Oka
O?Qzru B   缓存依赖
dev7^1l C8t
NYiq6Kqz"[P   缓存依赖允许缓存项依赖于另外一个资源,这样资源变化时,缓存项自动移出。
;Q|)@3V X'Z *v3qMB1e RuT
  ASP.NET包括3种依赖类型6@,v Mh3p#G jR
"F`-~-@!y;]
  依赖于其他缓存项
#|$~)O%a$[*ISn ;ZK'orv
  依赖于文件或文件夹
fXm~sC WNw Y,j f`I
  依赖于数据库查询。
F XIapwS wm
2v8A)J0ij D|   另外你还可以使用聚合依赖,或是自定义缓存依赖。5ki \5n,Y%u Y

L#q2~9\#{!R7NL4[   缓存功能也有其自身的不足。例如,显示的内容可能不是最新、最准确的,为此,必须设置合适的缓存策略。缓存增加了系统的复杂性并使其难于测试和调试,你设置的断点、监控变量等由于缓存在调试时都可能无效。
)s$n5|'nR4e S /~!x.v4R Jop:}yy
  2. Rainbow Portal中的数据缓存"fBd|.GA%v6[(W6x

"g] t oC!Wq   Rainbow Portal的Portal、页面、模块的配置信息、页面布局、主题等信息全部保存到数据库里,若是每次从数据据库读取,就会影响性能。Rainbow自此处理上使用了数据缓存技术。
y"@GLw+|%UJ 'p6pTBL1Y
  两个辅助类:]G._G2v\A&fO
GU6B$`!wi
  Rainbow.Framework.Settings.Cache.Key 实现缓存键名的获取,其方法都是静态的。由于Rainbow一个网站可以包含多个Portal,每个Portal都有独立的设置,因此缓存的键名要区分不同的Portal。Key类为键名每个加上Portal的别名作为前缀。
5W]zPIUPf'T \ #X @@hfx0O
  如获取Portal配置信息的键名:%rBhwuL

3R9_ p+J,KH,gV 以下是引用片段:8n5nV5X2D.H.Er,_&] r
  public static string PortalSettings()
TF(y6g*Mv   {
@'J.u~T   return string.Concat(Portal.UniqueID, "_PortalSettings");
7Z+\:lg/rZk'f4_%[   } j/h&[D5AS.pB
  Rainbow.Framework.Settings.Cache.CurrentCache类封装对当前缓存的操作。
&U1J| Y&r7l)iBW   Rainbow.Framework.Site.Configuration命名空间中的PortalSettings类,PageSettings类,ModuleSettings类;Rainbow.Framework.Design命名空间中的LayoutManager类,ThemeManager类等,都应用了缓存技术。一般过程为:先判断当前的Cache里有没有缓存值,若有则从缓存中直接读取,若没有就从数据库中读取,然后保存到当前缓存中。
&G&uD+s"w3a   以PortalSettings类为例说明: *q1^$j(xU0q(R}%K0|3P
  public class PortalSettings
zQ\-n'jy   { (Rh&y0s9r&LN AG%i5p
  ...... yyq4[`uISg
  public static Hashtable GetPortalBaseSettings(string PortalPath)
R,VX#v,AF'X   { !k3J\%G2M*l |
  Hashtable _baseSettings; gy})pf `%Ez,j3n
  if (!CurrentCache.Exists(Key.PortalBaseSettings())) Y:HrXVJJ7Sim
  {
aWB,V-}A6BG"D   //从数据库里读取
/x*Y0`@ HI+}F/U q   ...... K1nz-yok({X
  保存到缓存中 &Y_9x{$dF8|%d)^
  CacheDependency settingDependencies =
7Ezb\~hhT#{%y   new CacheDependency( l i'\5Kss I
  new string[] {+SD] GM [dm*T!W
  {
3M9S{8~h,kE   LayoutManager.Path,
PH"b#@8g)S4Rq   layoutManager.PortalLayoutPath,
'|OW*W [wh8x)f2v$LH8F   ThemeManager.Path, o7\X$h }+k;z$?)m?
  themeManager.PortalThemePath IZ5rj.yGu8V3Fq
  });
j{? EY sWg*S   using (settingDependencies) 6|Vl;R&x*W6x
  {
N ? Ux?%ni Z   CurrentCache.Insert(Key.PortalBaseSettings(), _baseSettings, settingDependencies);
:Jt"MU.Y+U)o V   } TN&zOE|s7L*q
  } qf)OD)CML6Z O
  else G5tkon uN"kN
  {
m`~"g+oB   _baseSettings = (Hashtable)CurrentCache.Get(Key.PortalBaseSettings()); 5{2f f1U+V-m
  } |,xez.D*?0SO
  return _baseSettings;
R4?[D U   } $Yg+b9a$aLG
  }
cbU-O/nr   针对缓存移除的问题,Rainbow一方面采用了缓存依赖自动移除,如上述代码中的settingDependencies,另外一方面在程序中显式移出,如在PortalSettings类中,当更改Portal配置后,就移除缓存:
m*p'qO2Mq
])MmJ|]'\.i 以下是引用片段:p zo FyNb-s
  public static void UpdatePortalSetting(int portalID, string key, string value)
W.NUsw HI   { jl^-RR
  //更新
$A8K"@@,fF   .... ~6n~ o VS
  CurrentCache.Remove(Key.PortalSettings()); 1N4r6Ve wwR
  }
B6M2s.X*n2GC'}   Rainbow Portal的一些模块中,也用到了缓存技术,但有些存在一定问题,如WhosLoggedOn模块中也使用了数据缓存,但是并没有通过Rainbow.Framework.Settings.Cache.Key类实现缓存键名的获取,这样在一个站点存在多个Portal的时候,站点的统计数会出现不正确的情况。

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.