ASP.NET性能优化之构建自定义文件缓存

标签: asp net 性能优化 | 发表时间:2011-09-08 09:21 | 作者:陆敏技 Pei
出处:http://www.cnblogs.com/

ASP.NET的输出缓存(即静态HTML)在.NET4.0前一直是基于内存的。这意味着如果我们的站点含有大量的缓存,则很容易消耗掉本机内存。现在,借助于.NET4.0中的OutputCacheProvider,我们可以有多种选择创建自己的缓存。如,我们可以把HTML输出缓存存储到memcached分布式集群服务器,或者MongoDB中(一种常用的面向文档数据库,不妨阅读本篇http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx)。当然,我们也可以把缓存作为文件存储到硬盘上,考虑到可扩展性,这是一种最廉价的做法,本文就是介绍如果构建自定义文件缓存。

1:OutputCacheProvider

OutputCacheProvider是一个抽象基类,我们需要override其中的四个方法,它们分别是:

Add 方法,将指定项插入输出缓存中。

Get 方法,返回对输出缓存中指定项的引用。

Remove 方法,从输出缓存中移除指定项。

Set 方法,将指定项插入输出缓存中,如果该项已缓存,则覆盖该项。

2:创建自己的文件缓存处理类

该类型为FileCacheProvider,代码如下:

    public class FileCacheProvider : OutputCacheProvider
    {
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public override void Initialize(string name, NameValueCollection attributes)
        {
            base.Initialize(name, attributes);
            CachePath = HttpContext.Current.Server.MapPath(attributes["cachePath"]);
        }

        public override object Add(string key, object entry, DateTime utcExpiry)
        {
            Object obj = Get(key);
            if (obj != null)    //这一步很重要
            {
                return obj;
            }
            Set(key,entry,utcExpiry);
            return entry;
        }

        public override object Get(string key)
        {
            string path = ConvertKeyToPath(key);
            if (!File.Exists(path))
            {
                return null;
            }
            CacheItem item = null;
            using (FileStream file = File.OpenRead(path))
            {
                var formatter = new BinaryFormatter();
                item = (CacheItem)formatter.Deserialize(file);
            }

            if (item.ExpiryDate <= DateTime.Now.ToUniversalTime())
            {
                log.Info(item.ExpiryDate + "*" + key);
                Remove(key);
                return null;
            }
            return item.Item;
        }


        public override void Set(string key, object entry, DateTime utcExpiry)
        {
            CacheItem item = new CacheItem(entry, utcExpiry);
            string path = ConvertKeyToPath(key);
            using (FileStream file = File.OpenWrite(path))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(file, item);
            }
        }
        
        public override void Remove(string key)
        {
            string path = ConvertKeyToPath(key);
            if (File.Exists(path))
                File.Delete(path);
        }

        public string CachePath
        {
            get;
            set;
        }

        private string ConvertKeyToPath(string key)
        {
            string file = key.Replace('/', '-');
            file += ".txt";
            return Path.Combine(CachePath, file);
        }
    }

    [Serializable]
    public class CacheItem
    {
        public DateTime ExpiryDate;
        public object Item;

        public CacheItem(object entry, DateTime utcExpiry)
        {
            Item = entry;
            ExpiryDate = utcExpiry;
        }
    }

有两个地方需要特别说明:

在Add方法中,有一个条件判断,必须做出这样的处理,否则缓存机制将会缓存第一次的结果,过了有效期后缓存讲失效并不再重建;

在示例程序中,我们简单的将缓存放到了Cache目录下,在实际的项目实践中,考虑到缓存的页面将是成千上万的,所以我们必须要做目录分级,否则寻找并读取缓存文件将会成为效率瓶颈,这会耗尽CPU。

3:配置文件

我们需要在Web.config中配置缓存处理程序是自定义的FileCacheProvider,即在  <system.web>下添加节点:

    <caching>
      <outputCache defaultProvider="FileCache">
        <providers>
          <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
        </providers>
      </outputCache>
    </caching>

4:缓存的使用

我们假设在MVC的控制中使用(如果要在ASP.NET页面中使用,则在页面中包含<%@OutputCache VaryByParam="none"  Duration="10" %>),可以看到,Index是未进行输出缓存的,而Index2进行了输出缓存,缓存时间为10秒。

    public class HomeController : Controller
    {
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        static string s_conn = "Data Source=192.168.0.77;Initial Catalog=luminjidb;User Id=sa;Password=sa;";
        public ActionResult Index()
        {
            using (DataSet ds = Common.SqlHelper.ExecuteDataset(s_conn, CommandType.Text, "select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"))
            {
                ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
            }
            return View();
        }

        [OutputCache(Duration = 10, VaryByParam = "none")]
        public ActionResult Index2()
        {
            using (DataSet ds = Common.SqlHelper.ExecuteDataset(s_conn, CommandType.Text, "select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"))
            {
                ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
            }
            return View();
        }
    }

5:查看下效果

上面的代码,在访问了Index2后,将会在Cache文件夹下产生缓存文件,如下:

image

现在,我们开始评价下有输出缓存和无输出缓存的性能对比,模拟100个用户并发1000次请求如下:

image

可以看到,有输出缓存后,吞吐率明显提高了10倍。

6:代码下载

FileCacheProvider的原始代码来自于网络,我修改了其中的BUG,全部代码下载如下:MvcApplication20110907.rar

作者: 陆敏技 发表于 2011-09-08 09:21 原文链接

评论: 19 查看评论 发表评论


最新新闻:
· Windows 8 版 Bing 应用将于下周发布?附截图和体验地址(2011-09-08 18:36)
· Google 应对甲骨文可能失利 & One more thing(2011-09-08 18:05)
· 巴茨任职期15 瞬间 :裁员 爆粗口 拒绝售股(2011-09-08 17:34)
· Ruby作者松本行弘将推出针对移动计算的Ruby分支(2011-09-08 17:30)
· Xbox 360名列8月美国畅销游戏机第一(2011-09-08 17:22)

编辑推荐:用ASP.NET写自己的服务框架

网站导航:博客园首页  我的园子  新闻  闪存  小组  博问  知识库

相关 [asp net 性能优化] 推荐:

Debugging .NET Core on Linux with LLDB | RayDBG

- -
The LLDB debugger is conceptually similar to the native Windows debugging tools in that it is a low level and command live driven debugger. Part of the reason the .NET Core team chose the LLDB debugger was for its extensibility points that allowed them to create the SOS plugin which can be used to debug .NET core applications.

MySQL性能优化

- sun - IT程序员面试网
在笔试面试中,尤其是像百度,淘宝这些数据量非常大,而且用LAMP架构的公司,数据库优化方面就显得特别重要了. 此外,除了数据库索引之外,在LAMP结果如此流行的今天,数据库(尤其是MySQL)性能优化也是海量数据处理的一个热点. 下面就结合自己的经验,聊一聊MySQL数据库优化的几个方面. 首先,在数据库设计的时候,要能够充分的利用索引带来的性能提升,至于如何建立索引,建立什么样的索引,在哪些字段上建立索引,上面已经讲的很清楚了,这里不在赘述.

Hebernate 性能优化

- - 企业架构 - ITeye博客
文章分为十三个小块儿对Hibernate性能优化技巧进行总结性分析,分析如下:. 一、在处理大数据量时,会有大量的数据缓冲保存在Session的一级缓存中,这缓存大太时会严重显示性能,所以在使用Hibernate处理大数 据量的,可以使用session. clear()或者session. evict(Object) 在处理过程中,清除全部的缓存或者清除某个对象.

Hbase 性能优化

- - CSDN博客云计算推荐文章
因 官方Book Performance Tuning部分章节没有按配置项进行索引,不能达到快速查阅的效果. 所以我以配置项驱动,重新整理了原文,并补充一些自己的理解,如有错误,欢迎指正. 默认值:3分钟(180000ms). 说明:RegionServer与Zookeeper间的连接超时时间.

JavaScript性能优化

- - ITeye博客
互联网泡沫让投资者长了记性:态度更加谨慎.         如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍JavaScript性能优化的技巧,并提供相应的测试用例,供大家在自己使用的浏览器上验证, 同时会对特定的JavaScript背景知识做一定的介绍.

Mysql性能优化

- - 数据库 - ITeye博客
MySQL性能优化.   性能优化是通过某些有效的方法来提高MySQL的运行速度,减少占用的磁盘空间. 性能优化包含很多方面,例如优化查询速度,优化更新速度和优化MySQL服务器等.   数据库管理人员可以使用SHOW STATUS语句来查询MySQL数据库的性能. 语法:SHOW STATUE LIKE ‘value’;其中value参数是常用的几个统计参数.

Linux 性能优化

- - Gsion&apos;s Blog
1) Linux Proc文件系统,通过对Proc文件系统进行调整,达到性能优化的目的. 2) Linux性能诊断工具,介绍如何使用Linux自带的诊断工具进行性能诊断. 加粗斜体表示可以直接运行的命令. 二、/proc/sys/kernel/优化. 该文件有一个二进制值,该值控制系统在接收到ctrl+alt+delete按键组合时如何反应.

hbase性能优化

- - CSDN博客推荐文章
  当你调用create方法时将会加载两个配置文件:hbase-default.xml and hbase-site.xml,利用的是当前的java类路径, 代码中configuration设置的这些配置将会覆盖hbase-default.xml和hbase-site.xml中相同的配置,如果两个配置文件都存在并且都设置好了相应参上面的属性下面的属性即可.

oracle性能优化

- - 行业应用 - ITeye博客
                              oracle数据库的性能优化. 主要从内部存储结构,逻辑分区,表结构范式,sql语句优化. hibernate处的层次更高,主要从缓存,和sql语句的使用.     对于ORACLE数据库的数据存取,主要有四个不同的调整级别,第一级调整是操作系统级包括硬件平台,第二级调整是ORACLE RDBMS级的调整,第三级是数据库设计级的调整,最后一个调整级是SQL级.

mssql性能优化

- - 数据库 - ITeye博客
一、             分析阶段. 一般来说,在系统分析阶段往往有太多需要关注的地方,系统各种功能性、可用性、可靠性、安全性需求往往吸引了我们大部分的注意力,但是,我们必须注意,性能是很重要的非功能性需求,必须根据系统的特点确定其实时性需求、响应时间的需求、硬件的配置等. 另一方面,在分析阶段应该根据各种需求区分出系统的类型,大的方面,区分是OLTP(联机事务处理系统)和OLAP(联机分析处理系统).