您的位置:首页 > 编程语言 > ASP

细说 ASP.NET Cache 及其高级用法

2017-10-24 10:54 387 查看
转自:http://www.cnblogs.com/fish-li/archive/2011/12/27/2304063.html#!comments

许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术。 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用HttpRuntime.Cache访问到的那个Cache,而不是其它的缓存技术。

以前我在【我心目中的Asp.net核心对象】 这篇博客中简单地提过它,今天我打算为它写篇专题博客,专门来谈谈它,因为它实在是太重要了。在这篇博客中, 我不仅要介绍它的一些常见用法,还将介绍它的一些高级用法。 在上篇博客【在.net中读写config文件的各种方法】 的结尾处,我给大家留了一个问题,今天,我将在这篇博客中给出一个我认为较为完美的答案。

本文提到的【延迟操作】方法(如:延迟合并写入数据库)属于我的经验总结,希望大家能喜欢这个思路。

Cache的基本用途

提到Cache,不得不说说它的主要功能:改善程序性能。
ASP.NET是一种动态页面技术,用ASP.NET技术做出来的网页几乎都是动态的,所谓动态是指:页面的内容会随着不同的用户或者持续更新的数据, 而呈现出不同的显示结果。既然是动态的,那么这些动态的内容是从哪里来的呢?我想绝大多数网站都有自己的数据源, 程序通过访问数据源获取页面所需的数据,然后根据一些业务规则的计算处理,最后变成适合页面展示的内容。

由于这种动态页面技术通常需要从数据源获取数据,并经过一些计算逻辑,最终变成一些HTML代码发给客户端显示。而这些计算过程显然也是有成本的。 这些处理成本最直接可表现为影响服务器的响应速度,尤其是当数据的处理过程变得复杂以及访问量变大时,会变得比较明显。 另一方面,有些数据并非时刻在发生变化,如果我们可以将一些变化不频繁的数据的最终计算结果(包括页面输出)缓存起来, 就可以非常明显地提升程序的性能,缓存的最常见且最重要的用途就体现在这个方面。 这也是为什么一说到性能优化时,一般都将缓存摆在第一位的原因。 我今天要说到的ASP.NET Cache也是可以实现这种缓存的一种技术。 不过,它还有其它的一些功能,有些是其它缓存技术所没有的。

Cache的定义

在介绍Cache的用法前,我们先来看一下Cache的定义:(说明:我忽略了一些意义不大的成员)

private static int s_RunOptionsCacheDependencyFlag = 0;

public static RunOptions LoadRunOptions()
{
string path = Path.Combine(AppDataPath, "RunOptions.xml");
// 注意啦:访问文件是可能会出现异常。不要学我,我写的是示例代码。
RunOptions options = RwConfigDemo.XmlHelper.XmlDeserializeFromFile<RunOptions>(path, Encoding.UTF8);

int flag = System.Threading.Interlocked.CompareExchange(ref s_RunOptionsCacheDependencyFlag, 1, 0);

// 确保只调用一次就可以了。
if( flag == 0 ) {
// 让Cache帮我们盯住这个配置文件。
CacheDependency dep = new CacheDependency(path);
HttpRuntime.Cache.Insert(RunOptionsCacheKey, "Fish Li", dep,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, RunOptionsUpdateCallback);
}

return options;
}

public static void RunOptionsUpdateCallback(
string key, CacheItemUpdateReason reason,
out object expensiveObject,
out CacheDependency dependency,
out DateTime absoluteExpiration,
out TimeSpan slidingExpiration)
{
// 注意哦:在这个方法中,不要出现【未处理异常】,否则缓存对象将被移除。

// 说明:这里我并不关心参数reason,因为我根本就没有使用过期时间
//        所以,只有一种原因:依赖的文件发生了改变。
//        参数key我也不关心,因为这个方法是【专用】的。

expensiveObject = "http://www.cnblogs.com/fish-li/";
dependency = new CacheDependency(Path.Combine(AppDataPath, "RunOptions.xml"));
absoluteExpiration = Cache.NoAbsoluteExpiration;
slidingExpiration = Cache.NoSlidingExpiration;

// 重新加载配置参数
s_RunOptions = LoadRunOptions();
}


View Code
改动很小,只是LoadRunOptions方法做了修改了而已,但是效果却很酷。

还记得我在上篇博客【在.net中读写config文件的各种方法】的结尾处留下来的问题吗? 这个示例就是我的解决方案。

文件监视技术的选择

对于文件监视,我想有人或许会想到FileSystemWatcher。正好我就来说说关于【文件监视技术】的选择问题。
说明,本文所有结论均为我个人的观点,仅供参考。

这个组件,早在做WinForm开发时就用过了,对它也是印象比较深的。
它有一个包装不好的地方是:事件会重复发出。比如:一次文件的保存操作,它却引发了二次事件。
什么,你不信? 正好,我还准备了一个示例程序。



说明:图片中显示了发生过二次事件,但我只是在修改了文件后,做了一次保存操作而已。 本文的结尾处有我的示例程序,您可以自己去试一下。这里为了方便,还是贴出相关代码:

private void Form1_Shown(object sender, EventArgs e)
{
this.fileSystemWatcher1.Path = Environment.CurrentDirectory;
this.fileSystemWatcher1.Filter = "RunOptions.xml";
this.fileSystemWatcher1.NotifyFilter = System.IO.NotifyFilters.LastWrite;
this.fileSystemWatcher1.EnableRaisingEvents = true;
}

private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
{
string message = string.Format("{0} {1}.", e.Name, e.ChangeType);
this.listBox1.Items.Add(message);
}


对于这个类的使用,只想说一点:会引发的事件很多,因此一定要注意过滤。以下引用MSDN的一段说明:

Windows 操作系统在 FileSystemWatcher 创建的缓冲区中通知组件文件发生更改。如果短时间内有很多更改,则缓冲区可能会溢出。这将导致组件失去对目录更改的跟踪,并且它将只提供一般性通知。使用 InternalBufferSize 属性来增加缓冲区大小的开销较大,因为它来自无法换出到磁盘的非页面内存,所以应确保缓冲区大小适中(尽量小,但也要有足够大小以便不会丢失任何文件更改事件)。若要避免缓冲区溢出,请使用 NotifyFilter 和 IncludeSubdirectories 属性,以便可以筛选掉不想要的更改通知。

幸运的是,ASP.NET Cache并没有使用这个组件,我们不用担心文件依赖而引发的重复操作问题。 它直接依赖于webengine.dll所提供的API,因此,建议在ASP.NET应用程序中,优先使用Cache所提供的文件依赖功能。

各种缓存方案的共存

ASP.NET Cache是一种缓存技术,然而,我们在ASP.NET程序中还可以使用其它的缓存技术, 这些不同的缓存也各有各自的长处。由于ASP.NET Cache不能提供对外访问能力,因此,它不可能取代以memcached为代表的分布式缓存技术, 但它由于是不需要跨进程访问,效率也比分布式缓存的速度更快。如果将ASP.NET Cache设计成【一级缓存】, 分布式缓存设计成【二级缓存】,就像CPU的缓存那样,那么将能同时利用二者的所有的优点,实现更完美的功能以及速度。

其实缓存是没有一个明确定义的技术,一个static变量也是一个缓存,一个static集合就是一个缓存容器了。 这种缓存与ASP.NET Cache相比起来,显然static变量的访问速度会更快,如果static集合不是设计得很差的话, 并发的冲突也可能会比ASP.NET Cache小,也正是因为这一点,static集合也有着广泛的使用。 然而,ASP.NET Cache的一些高级功能,如:过期时间,缓存依赖(包含文件依赖),移除通知,也是static集合不具备的。 因此,合理地同时使用它们,会让程序有着最好的性能,也同时拥有更强大的功能。

点击此处下载示例代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: