当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > 小议优化ASP.NET应用性能之Cache篇

ASP.NET
二级域名Cookie问题的解决方法
如何为asp.net网站项目添加子项目
asp.net用url重写URLReWriter实现任意二级域名
asp.net 序列化and反序列化演示
asp.net Timer的使用方法
AjaxControlToolKit DropDownExtender(下拉扩展控件)使用方法
AjaxControlToolKit CalendarExtender(日历扩展控件)的使用方法
让GridView只显示特定用户的数据的方法
让GridView只更新某些特定的数据的方法
ajaxControlToolkit中CascadingDropDown的用法说明
axp.net ScriptManager的简单用法
把程序集安装到全局程序集缓存中的步骤
引用全局程序集缓存内的程序集的方法
asp.net COOKIES需要注意的一点
asp.net UrlReWriter使用经验小结
页面导出为Excel的时间格式的问题
asp.net cookie清除的代码
Asp.net XMLHTTP封装类(GET,Post发送和接收数据)
ASP.NET XmlHttp跨域访问实现代码
Asp.NET 随机码生成基类(随机字母,随机数字,随机字母+数字)

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-14   浏览: 191 ::
收藏到网摘: n/a

虽然现在已经是宽带时代,小猫已经离我们渐渐远去,可作为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}: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.若有不妥之处还望各位同行指正。