打印

[asp.net教程] 小议优化asp.net应用性能之cache篇

小议优化asp.net应用性能之cache篇

虽然现在已经是宽带时代,小猫已经离我们渐渐远去,可作为web应用开发者来说,我们仍然有责任和义务不断地通过技术手段来优化web应用性能,让用户浏览时少一些等待,多一些爽快。
   所幸的是,asp.net作为基于.net framework的web开发技术,它也享用着.net framework的优越性,.net framework为我们提供了良好的cache技术,使我们能开发出速度更快、用户体验更好的web应用。命名空间 system.web.caching提供了cache类,其cache的有效性依赖分以下三种情况:
  1. 时间点(指定时间点内有效);
  2. key值(key值作cache项标识);
  3. 文件或目录(指定文件或目录变更,则原cache项不可用);
   
   
   下面我就结合实际开发的应用跟大家分享一下使用cache来提高asp.net应用的性能。
   我们在开发中常常会遇到读取记录列表(例如最近更新的新闻列表top n)、记录本身(例如一条新闻),用户访问的时候,这样的信息是否每次都要重复从数据库中读取呢?聪明的你可能知道,这完全是没必要的。
   
  我们为了方便处理,不防设计一个sitecache类(借鉴了cs中的cscache.cs),并提供若干静态方法,来负责处理cache项的添加和删除。
   
  代码:
   
   
  sitecache.cs
   1using system;
   2using system.collections;
   3using system.text.regularexpressions;
   4using system.web;
   5using system.web.caching;
   6
   7namespace ycweb.components
   8{
   9 public class sitecache
   10 {
   11 private static readonly cache _cache;
   12 public static readonly int dayfactor;
   13 private static int factor;
   14 public static readonly int hourfactor;
   15 public static readonly int minutefactor;
   16
   17 static sitecache()
   18 {
   19 dayfactor = 17280;
   20 hourfactor = 720;
   21 minutefactor = 12;
   22 factor = 5;
   23 _cache = httpruntime.cache;
   24 }
   25
   26 private sitecache()
   27 {
   28 }
   29
   30 public static void clear()
   31 {
   32 idictionaryenumerator enumerator = _cache.getenumerator();
   33 while (enumerator.movenext())

   34 {
   35 _cache.remove(enumerator.key.tostring());
   36 }
   37 }
   38
   39 public static object get(string key)
   40 {
   41 return _cache[key];
   42 }
   43
   44 public static void insert(string key, object obj)
   45 {
   46 insert(key, obj, null, 1);
   47 }
   48
   49 public static void insert(string key, object obj, int seconds)
   50 {
   51 insert(key, obj, null, seconds);
   52 }
   53
   54 public static void insert(string key, object obj, cachedependency dep)
   55 {
   56 insert(key, obj, dep, hourfactor*12);
   57 }
   58
   59 public static void insert(string key, object obj, int seconds, cacheitempriority priority)
   60 {
   61 insert(key, obj, null, seconds, priority);
   62 }
   63
   64 public static void insert(string key, object obj, cachedependency dep, int seconds)
   65 {
   66 insert(key, obj, dep, seconds, cacheitempriority.normal);
   67 }
   68
   69 public static void insert(string key, object obj, cachedependency dep, int seconds, cacheitempriority priority)
   70 {
   71 if (obj != null)
   72 {
   73 _cache.insert(key, obj, dep, datetime.now.addseconds((double) (factor*seconds)), timespan.zero, priority, null);
   74 }
   75 }
   76
   77 public static void max(string key, object obj)
   78 {
   79 max(key, obj, null);
   80 }
   81
   82 public static void max(string key, object obj, cachedependency dep)
   83 {
   84 if (obj != null)
   85 {
   86 _cache.insert(key, obj, dep, datetime.maxvalue, timespan.zero, cacheitempriority.abovenormal, null);
   87 }
   88 }
   89
   90 public static void microinsert(string key, object obj, int secondfactor)
   91 {
   92 if (obj != null)
   93 {
   94 _cache.insert(key, obj, null, datetime.now.addseconds((double) (factor*secondfactor)), timespan.zero);
   95 }
   96 }
   97
   98 public static void remove(string key)
   99 {
  100 _cache.remove(key);
  101 }
  102
  103 public static void removebypattern(string pattern)
  104 {
  105 idictionaryenumerator enumerator = _cache.getenumerator();
  106 regex regex1 = new regex(pattern, regexoptions.singleline regexoptions.compiled regexoptions.ignorecase);
  107 while (enumerator.movenext())
  108 {
  109 if (regex1.ismatch(enumerator.key.tostring()))
  110 {
  111 _cache.remove(enumerator.key.tostring());
  112 }
  113 }
  114 }
  115
  116 public static void resetfactor(int cachefactor)
  117 {
  118 factor = cachefactor;
  119 }
  120
  121
  122
  123 }
  124}
   
   其实该类主要就是利用前文所提及的关于cache依赖项的第一点与第二点的特性来维护我们自己的cache项。
  有了sitecache类,接下来看看如何使用它。还是以读取新闻tonn列表为例:
   
   
   1public static recordset getnewssettopn(string classcode,int topn,sortpostsby orderby, sortorder sortorder, string language)
   2{
   3 string cachekey = string.format("newssettopn-lg:{0}:cc:{1}:tn:{2}b:{3}:so:{4}", language,classcode,topn.tostring(), orderby.tostring(),sortorder.tostring());
   4
   5 //从上下文中读缓存项
   6 recordset newsset = httpcontext.current.items[cachekey] as recordset;
   7 if (newsset == null)
   8 {
   9 //从httpruntime.cache读缓存项
  10 newsset = sitecache.get(cachekey) as recordset;
  11 if (newsset == null)
  12 {
  13 //直接从数据库从读取
  14 commondataprovider dp=commondataprovider.instance();
  15 newsset =dp.getnewssettopn(language,classcode,topn,orderby,sortorder);
  16 //并将结果缓存到httpruntime.cache中
  17 sitecache.insert(cachekey, newsset, 60, cacheitempriority.normal);
  18 }
  19
  20 }
  21return newsset;
  22}
   
   
   这样在5分钟内就不用重复访问数据库了来读该列表了,当然,也有人会问,如果在这5分钟内某条新闻删除了或修改了怎么办,没关系,我们在删除或修改时可以根据cache key来强制删除该cache项,当然,如果你觉得你对列表的时效性不是特别在意,你可以不强制删除该cache项,让cache项定义的时间点自动失效。当然,最好还是提供一个方法按匹配模式项来强行删除cache项就可以了,例如:
   
   
   
  1/**//// <summary>
  2/// 删除匹配的newssettopn列表的cache项
  3/// </summary>
  4public static void clearnewssettopncache(string language,string classcode,int topn)
  5{
  6 string cachekey = string.format("newssettopn-lg:{0}:cc:{1}:tn:{2}",language,classcode,topn.tostring());
  7 sitecache.removebypattern(cachekey);
  8}
  9
   
   发布新闻后调用静态方法clearnewssettopncache()强行清除原来的topn缓存项,例如:
   
   
   
   1/**//// <summary>
   2/// 发布(新建)新闻
   3/// </summary>
   4/// <param name="post">新闻实例</param>
   5/// <returns>返回状态</returns>
   6public static int create(news post)
   7{
   8 int status;
   9 commondataprovider dp=commondataprovider.instance();
  10 dp.createupdatedeletenews(post, dataaction.create, out status);
  11 //强制清除匹配的缓存项
  12 clearnewssettopncache (post.language, post.classcode,globals.getsitesetting.newslisttopn);
  13 return status;
  14}
   
   
  that's all.若有不妥之处还望各位同行指正。

TOP

返回顶部
AYBlue

Processed in 0.063931 second(s), 7 queries.

当前时区 GMT+8, 现在时间是 2009-1-10 11:47 京ICP备06054220号

清除 Cookies - 联系我们 - 163K.com - Archiver - WAP