首页 > 编程 > .NET > 正文

小议优化ASP.NET应用性能之Cache篇

2024-07-10 13:10:04
字体:
来源:转载
供稿:网友

  虽然现在已经是宽带时代,小猫已经离我们渐渐远去,可作为web应用开发者来说,我们仍然有责任和义务不断地通过技术手段来优化web应用性能,让用户浏览时少一些等待,多一些爽快。

  所幸的是,asp.net作为基于.net framework的技术,它也享用着.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}:ob:{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.若有不妥之处还望各位同行指正。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表