asp.net缓存要注意些什么?,第1张

aspnet性能的技巧

IT168 技术文档根据经验的总结,让我们来看看十个能帮助你提升你的应用程序性能的经验,我将按将它们提升效率的多少从大到小小依次说明。

一、返回多个数据

检查你的访问数据库的代码,看是否存在着要返回多次的请求。每次往返降低了你的应用程序的每秒能够响应请求的次数。通过在单个数据库请求中返回多个结果集,可以减少与数据库通信的时间,使你的系统具有扩展性,也可以减少数据库服务器响应请求的工作量。

如果你是用动态的SQL语句来返回多个数据集,那我建议你用存储过程来替代动态的SQL语句。是否把业务逻辑写到存储过程中,这个有点争议。但是我认为,把业务逻辑写到存储过程里面可以限制返回结果集的大小,减小网络数据的流量,在逻辑层也不用在过滤数据,这是一个好事情。

用SqlCommand对象的ExecuteReader方法返回一个强类型的业务对象,再调用NextResult方法来移动数据集指针来定位数据集。示例一演示了一个返回多个ArrayList强类型对象的例子。只从数据库中返回你需要的数据可以大大的减小你的服务器所耗用的内存。

二、对数据进行分页

ASPNET的DataGrid有一个非常有用的功能:分页。如果DataGrid允许分页,在某一时刻它只下载某一页的数据,另外,它有一个数据分页的浏览导航栏,它让你可以选择浏览某一页,而且每次只下载一页的数据。

但是它有一个小小的缺点,就是你必须把所有的数据都绑定到DataGrid中。也就是说,你的数据层必须返回所有的数据,然后DataGrid再根据当前页过滤出当前页所需要的数据显示出来。如果有一个一万条记录的结果集要用DataGrid进行分页,假设DataGrid每页只显示25条数据,那就意味着每次请求都有9975条数据都是要丢弃的。每次请求都要返回这么大的数据集,对应用程序的性能影响是非常大的。

一个好的解决方案是写一个分页的存储过程,例子2是一个用于对Northwind数据库orders表的分页存储过程。你只需要传当前页码,每页显示的条数两个参数进来,存储过程会返回相应的结果。

在服务器端,我专门写了一个分页的控件来处理数据的分页,在这里,我用了第一个方法,在一个存储过程里面返回了两个结果集:数据记录总数和要求的结果集。

返回的记录总数取决于要执行查询,例如,一个where条件可以限制返回的结果集的大小。因为在分页界面中必须要根据数据集记录的大小来计算总的页数,所以必须要返回结果集的记录数。例如,如果一共有1000000条记录,如果用where条件就可以过滤成只返回1000条记录,存储过程的分页逻辑应该知道返回那些需要显示的数据。

三、连接池

用TCP来连接你的应用程序与数据库是一件昂贵的事情(很费时的事情),微软的开发者可以通过用连接池来反复的使用数据库的连接。比起每次请求都用TCP来连一次数据库,连接池只有在不存在有效的连接时才新建一个TCP连接。当关闭一个连接的时候,它会被放到池中,它仍然会保持与数据库的连接,这样就可以减少与数据库的TCP连接次数。

当然,你要注意那些忘记关的连接,你应在每次用完连接后马上关闭它。我要强调的是:无论什么人说NET Framework中的GC(垃圾收集器)总会在你用完连接对象后调用连接对象的Close或者Dispose方法显式的关闭你的连接。不要期望CLR会在你想象的时间内关掉连接,虽然CLR最终都要销毁对象和关闭边接,但是我们并不能确定它到底会在什么时候做这些事情。

要用连接池优化,有两条规则,第一,打开连接,处理数据,然后关闭连接。如果你必须在每次请求中多次打开或关闭连接,这好过一直打开一个边接,然后把它传到各个方法中。第二,用相同的连接字符串(或者用相同的用户标识,当你用集成认证的时候)。如果你没有用相同的连接字符串,如你用基于登录用户的连接字符串,这将不能利用连接池的优化功能。如果你用的是集成的论证,因为用户很多,所以你也不能充分利用连接池的优化功能。NET CLR提供了一个数据性能计数器,它在我们需要跟踪程序性能特性的时候非常有用,当然也包括连接池的跟踪了。

无论你的应用程序什么时候要连在另一台机子的资源,如数据库,你都应该重点优化你连资源所花的时间,接收和发送数据的时间,以及往返回之间的次数。优化你的应用程序中的每一个处理点(process hop),它是提高你的应用的性能的出发点。

应用程序层包含与数据层连接,传送数据到相应的类的实例以及业务处理的逻辑。例如,在Community Server中,要组装一个Forums或者Threads集合,然后应用业务逻辑,如授权,更重要的,这里要完成缓存逻辑。

四、 ASPNET缓存API

在写应用程序之前,你要做的第一件事是让应用程序最大化的利用ASPNET的缓存功能。

如果你的组件是要在Aspnet应用程序中运行,你只要把SystemWebdll引用到你的项目中就可以了。然后用HttpRuntimeCache属性就可访问Cache了(也可以通过PageCache或HttpContextCache访问)。

有以下几条缓存数据的规则。第一,数据可能会被频繁的被使用,这种数据可以缓存。第二,数据的访问频率非常高,或者一个数据的访问频率不高,但是它的生存周期很长,这样的数据最好也缓存起来。第三是一个常常被忽略的问题,有时候我们缓存了太多数据,通常在一台X86的机子上,如果你要缓存的数据超过800M的话,就会出现内存溢出的错误。所以说缓存是有限的。换名话说,你应该估计缓存集的大小,把缓存集的大小限制在10以内,否则它可能会出问题。在Aspnet中,如果缓存过大的话也会报内存溢出错误,特别是如果缓存大的DataSet对象的时候。

这里有几个你必须了解的重要的缓存机制。首先是缓存实现了“最近使用”原则( a least-recently-used algorithm),当缓存少的时候,它会自动的强制清除那些无用的缓存。其次 “条件依赖”强制清除原则(expiration dependencies),条件可以是时间,关键字和文件。以时间作为条件是最常用的。在aspnet20中增加一更强的条件,就是数据库条件。当数据库中的数据发生变化时,就会强制清除缓存。要更深入的了解数据库条件依赖请看Dino Esposito 在MSDN杂志2004年七月刊的Cutting Edge专栏文章。

五、 预请求缓存

在前面,我提到过即使我们只对某些地方作了一个小小的性能改进也可以获得大的性能提升,我非常喜欢用预请求缓存来提升程序的性能。

虽然Cache API设计成用来保存某段时间的数据,而预请求缓存只是保存某个时期的某个请求的内容。如果某个请求的访问频率高,而且这个请求只需要提取,应用,修改或者更新数据一次。那么就可以预缓存该请求。我们举个例子来说明。

在CS的论坛应用程序中,每一个页面的服务器控件都要求得到用于决定它的皮肤(skin)的自定义的数据,以决定用哪个样式表及其它的一些个性化的东西。这里面的某些数据可能要长时间的保存,有些时间则不然,如控件的skin数据,它只需要应用一次,而后就可以一直使用。

要实现预请求缓存,用Aspnet 的HttpContext类,HttpContext类的实例在每一个请求中创建,在请求期间的任何地方都可以通过HttpContextCurrent属性访问。HttpContext类有一个Items集合属性,在请求期间所有的对象和数据都被添加到这个集合中缓存起来。和你用Cache缓存访问频率高数据一样,你可以用HttpContextItems缓存那些每个请求都要用到的基础数据。它背后的逻辑很简单:我们向HttpContextItems中添加一个数据,然后再从它里面读出数据。

你思路有问题。其实这个问题很好解决。就是一个缓存和数据库同步的问题。有两个方案供你参考,当然具体代码自己去写,我只提供你思路。

一、SQL SERVER2005以上版本的依赖式缓存,这个解决方案就是当数据库的数据有更新的时候会自动更新到缓存里。具体怎么配置,网上查找下,教程很多。

二、自己写数据库和缓存的数据同步代码。当客户端把更新数据库的数据操作的时候同时更新缓存里的数据。毕竟写比读少了很多。但是在写缓存的时候,必须注意一个问题,那就是公共缓存对象并发控制的问题,别出现死锁,或者脏读,幻读这类的线程锁出错的问题。。。记住一定要在写缓存的时候锁住它。。。数据库其实在写的时候也是排它锁的。只不过被数据库系统自身处理掉了。你写数据库数据时感觉不到而已。

 以前对缓存的认识比较零碎 最近做的行业新闻项目可能会大量应用的缓存技术 故将缓存技术再重新整理了下 使我自己对缓存又有了一个全新的认识 同时也给大家分享下

  页输出缓存

  全部输出缓存

 页输出缓存在内存中存储处理后的 ASP NET 页的内容 这一机制允许 ASP NET 向客户端发送页响应 而不必再次经过页处理生命周期 页输出缓存对于那些不经常更改 但需要大量处理才能创建的页特别有用

 要实现页输出缓存也很简单 如你要对default aspx页面实施页面缓存 那么你只需在defualt aspx页面中添加使用OutputCache指令 OutputCache有多个属性 其中两个必须的属性是Duration和VaryByParam Duration设置了缓存的过期时间 单位为秒 VaryByParam允许我们缓存页面的不同版本 一般情况下 VaryByParam设置为none 具体示例如下

 <%@ OutputCache Duration= VaryByParam= none %>

 这个设置就是说明 缓存时间是 秒 并且不分版本 其实加上了这句就已经完成了页输出缓存设置了 为了看下效果 我在default aspx cs文件Page_Load方法中添加了Response Write(DateTime Now ToString( yyyy MM dd HH:mm:ss ))一句 浏览页面后不断刷新 发现时间并不会改变 当缓存过期时间( 秒)到点了 刷新才会引起页面的变化

 上面已经实现了的页输出缓存 但是有一个问题 现在是一个网页 设置缓存可以放在default aspx中 但是如果一个网站有成千上万个网页 并且每个页面都需要设置缓存机制 一旦缓存时间需要修改时 就会涉及到要修改千万个网页 这样做肯定是很麻烦的事情 所以需要将网页的缓存设置放在一个公共地方 一旦需要修改的时候 调整起来比较方便 刚好的nfig文件中可以设置页面缓存 如下

 <system web>

 <caching>

 <outputCacheSettings>

 <outputCacheProfiles>

 <add name= pageCache duration= varyByParam= none enabled = true />

 </outputCacheProfiles>

 </outputCacheSettings>

 </caching>

 </system web>

 上面的意思为过期时间为 秒 不根据页面参数缓存

 页面中调用此设置如下

 <%@ OutputCache CacheProfile= pageCache %>

 这样 就完成了页输出缓存才配置

  片段缓存

 有些网页 可能大部分都不需要经常变更 比如页面头部和页脚 但是正文部分可能经常变动 像这些部分不经常变动而部分又经常变动的网页 可以采取片段缓存的办法 即 将不怎么变动的部分做成一个单独的用户控件(ascx) 调用的时间将这个ascx单独设置缓存 就能达到一个网页中经常变动不缓存 而不经常变动的部分缓存的效果了

  缓存后替换

 这种方式与片段缓存恰好相反 是将整个页面先缓存 然后将经常变动的地方单独做成一个ascx 并且这个ascx不设置缓存 如登录慧远保银首页 给每个人显得的内容都是一样的 唯独不一样的 就是在某个地方显示了当前的用户名不一样 这种情况就可以采取 缓存后替换 的办法 先将整个网页缓存 当然缓存下来的用户名可能是上个用户的 但是采取缓存后替换的方法 将你自己的用户名替换上个用户名 就能得到很好的效果了

  应用程序缓存

 第一部分说到的都是关于网页的缓存 缓存还提供另外一种缓存方式 即应用程序缓存 比如某个数据列表的计算需要花费很长时间 而且很浪费服务器资源 并且此列表不是需要经常更新的 那么我们可以先将此数据列表事先key/value的方式缓存在内存中 当有需要此数据时 可以以key的方式去寻找此数据列表

 如有一个DataSet对象ds 将它存入缓存的办法是 Cache[ ds ]=ds 当程序需要调用这个ds对象的时候 直接用Cache[ ds ]即可查询到数据值

 除了Cache[ ds ]=ds将数据缓存外 还提供了insert和add这两个方法将数据项添加到缓存 因为这两个函数功能大致相同 唯一区别就是 insert函数有替换功能 所以仅以insert作为示例简单说明下

 Insert方法有四个重载函数  

 对上面四个重载函数我作简要说明

    与Cache[ ds ]=ds类似 就是将数据以key/value的形式添加到缓存

    第二个重载函数多了一个CacheDependency类型的参数 这个参数的意义是指定添加数据的依赖项 比如 某个数据列表是从一个xml加载进来的 现在将此数据的依赖项设置为此xml文件 当xml文件修改后 此数据再缓存中自动删除 下次调用时重新加入缓存 这样可以保证缓存中的数据足够新

    第三个重载函数不仅指明了依赖项 还指明了缓存的有效时间 即在依赖项一直没有修改的情况下 过了有效时间 缓存数据依旧自动删除

lishixinzhi/Article/program/net/201311/12185

1整页缓存:优点:实现简单,缺点:消耗服务器内存

2片段缓存:优点:节省内存 缺点:实现麻烦

3应用程序缓存:优点:不局限缓存网页,缓存对象多样 确定:实现相对复杂

1可以这么说 但是net是存到内存 反正是在本地

2是的 net默认的缓存好像时间接近半小时 没注意过 一般我会自己设成 15分钟

3正确

4不会相差很远 但是net第一次加载偏慢 但是不可否认 肯定是 htm之类的纯静态页面速度会比较快

---------------------------------------

1不知道你的站点地图具体是什么 如果是静态的链接 不涉及到逻辑 权限等 完全可以用静态文件的

2服务器的配置一般教高 所以 执行net肯定是比本地快的 至于速度 还要取决于client的网络的速度

  可以使用@ OutputCache指令到缓存中,或者您可以以编程方式通过代码使用缓存的 Visual BasicNET 或 Visual C#NET。@ OutputCache指令中包含的位置属性。此属性确定缓存项的位置。您可以指定以下位置:

  任何-这将输出缓存存储在客户端的浏览器的代理服务器 (或其他任何服务器) 上参与在请求中,或在处理请求时的服务器上。默认情况下,任何选择。

  客户端-这将输出缓存存储在客户端浏览器。

  Downstream -这将输出缓存存储在请求中加入的任何缓存功能设备 (而不是源服务器上)。

  服务器-这将输出缓存存储在 Web 服务器上。

  无-这将关闭输出缓存。

  以下是代码示例的@ OutputCache指令和等效的编程代码。

  若要将输出缓存存储指定的持续时间

  声明性方法:

  <%@ OutputCache Duration="60" VaryByParam="None" %>

  编程的方法:

  ResponseCacheSetExpires(DateTimeNowAddSeconds(60));

  ResponseCacheSetCacheability(HttpCacheabilityPublic);

  在其中发出请求的浏览器客户端上存储输出缓存

  声明性方法:

  <%@ OutputCache Duration="60" Location="Client" VaryByParam="None" %>

  编程的方法:

  ResponseCacheSetExpires(DateTimeNowAddSeconds(60));

  ResponseCacheSetCacheability(HttpCacheabilityPrivate);

  在任何 HTTP 11 支持缓存的设备,包括代理服务器和发出请求的客户端上存储输出缓存

  声明性方法:

  <%@ OutputCache Duration="60" Location="Downstream" VaryByParam="None" %>

  编程的方法:

  ResponseCacheSetExpires(DateTimeNowAddSeconds(60));

  ResponseCacheSetCacheability(HttpCacheabilityPublic);

  ResponseCacheSetNoServerCaching();

  若要将输出缓存存储在 Web 服务器上

  声明性方法:

  <%@ OutputCache Duration="60" Location="Server" VaryByParam="None" %>

  编程的方法:

  TimeSpan freshness = new TimeSpan(0,0,0,60);

  DateTime now = DateTimeNow;

  ResponseCacheSetExpires(nowAdd(freshness));

  ResponseCacheSetMaxAge(freshness);

  ResponseCacheSetCacheability(HttpCacheabilityServer);

  ResponseCacheSetValidUntilExpires(true);

  缓存到达时,使用一个不同的城市每个 HTTP 请求的输出:

  声明性方法:

  <%@ OutputCache duration="60" varybyparam="City" %>

  编程的方法:

  ResponseCacheSetExpires(DateTimeNowAddSeconds(60));

  ResponseCacheSetCacheability(HttpCacheabilityPublic);

  ResponseCacheVaryByParams["City"] = true;

  VaryByCustom属性以及VaryByHeader属性中, @ OutputCache指令中的VaryByParam属性, HttpCachePolicy类提供的VaryByHeaders属性和VaryByParams属性中, SetVaryByCustom方法。

  关闭客户端和代理服务器缓存

  要关闭一个 ASPNET 网页,网页中的客户端位置和代理服务器位置的输出缓存,请将位置属性值设置为无,然后将VaryByParam值设置为无的@ OutputCache指令。使用下面的代码示例关闭客户端和代理服务器缓存。

  声明性方法:

  <%@ OutputCache Location="None" VaryByParam="None" %>

  编程的方法:

  ResponseCacheSetCacheability(HttpCacheabilityNoCache);

  缓存在服务器内存中的任意对象

  ASPNET 包括功能强大、 易于使用的缓存机制,可用于存储需要大量的服务器资源,在内存中创建的对象。缓存类中实现此方法。专用于每个应用程序实例,生存期依赖于相应的应用程序。若要通过使用缓存类缓存 ASPNet 中的任意对象,请执行以下步骤:

  通过使用 Visual C#net 中创建新的 ASPNET Web 应用程序。

  默认状态下,创建 WebForm1aspx。

  WebForm1aspx 的 HTML 视图中将现有代码替换下面的代码示例:

  <%@ Import Namespace="SystemData" %>

  <%@ Import Namespace="SystemDataSqlClient" %>

  <html>

  <script language="C#" runat="server">

  void Page_Load(Object Src, EventArgs E) {

  DataView Source;

  // Retrieve the DataView object from Cache If not exist, then add DataView object to the Cache

  Source = (DataView)Cache["MyDataSet"];

  if (Source == null) {

  SqlConnection myConnection = new SqlConnection("Server=ServerName; database=Pubs; user id=UID; password=PWD;");

  SqlDataAdapter myCommand = new SqlDataAdapter("select from Authors", myConnection);

  DataSet ds = new DataSet();

  myCommandFill(ds, "Authors");

  Source = new DataView(dsTables["Authors"]);

  Cache["MyDataSet"] = Source;

  CacheMsgText = "Dataset created explicitly";

  }

  else {

  CacheMsgText = "Dataset retrieved from cache";

  }

  // Binding the DataView object with DataGrid

  MyDataGridDataSource=Source;

  MyDataGridDataBind();

  }

  </script>

  <body>

  <form method="GET" runat="server">

  <h3><font face="Verdana">Caching Data</font></h3>

  <ASP:DataGrid id="MyDataGrid" runat="server"

  Width="700"

  BackColor="#ccccff"

  BorderColor="black"

  ShowFooter="false"

  CellPadding=3

  CellSpacing="0"

  Font-Name="Verdana"

  Font-Size="8pt"

  HeaderStyle-BackColor="#aaaad" />

  <p>

  <i><asp:label id="CacheMsg" runat="server"/></i>

  </form>

  </body>

  </html>

  注意 替换值的 ServerName、 UID,和 PWDSqlConnection 对象的示例代码中使用您的 SQL Server 名称、 用户 ID 和密码。

  在 调试 菜单上单击 $ 开始 以运行该应用程序。

  注意当您重新启动该应用程序时,高速缓存对象是重新创建。

如果你的服务器只有一台,且数据库读写压力不大,就没必要使用Memcached。HttpRuntimeCache是本地缓存,Memcached是分布式缓存,两者的区别在于:

本地缓存

本地缓存可能是大家用的最多的一种缓存方式了,不管是本地内存还是磁盘,其速度快,成本低,在有些场合非常有效。

但是对于web系统的集群负载均衡结构来说,本地缓存使用起来就比较受限制,因为当数据库数据发生变化时,你没有一个简单有效的方法去更新本地缓存;然而,你如果在不同的服务器之间去同步本地缓存信息,由于缓存的低时效性和高访问量的影响,其成本和性能恐怕都是难以接受的。

分布式缓存

前面提到过,本地缓存的使用很容易让你的应用服务器带上“状态”,这种情况下,数据同步的开销09会比较大;尤其是在集群环境中更是如此!

分布式缓存这种东西存在的目的就是为了提供比RDB更高的TPS和扩展性,同时有帮你承担了数据同步的痛苦;优秀的分布式缓存系统有大家所熟知的Memcached、Redis(当然也许你把它看成是NoSQL,但是我个人更愿意把分布式缓存也看成是NoSQL),还有淘宝自主开发的Tair等。

对比关系型数据库和缓存存储,其在读和写性能上的差距可谓天壤之别;就拿淘宝的Tair来说,mdb引擎的单机QPS已在10w以上,ldb的也达到了5w~7w,而集群的性能会更高(目前uic所用的Tair集群QPS高达数十万!)。

所以,在技术和业务都可以接受的情况下,我们可以尽量把读写压力从数据库转移到缓存上,以保护看似强大,其实却很脆弱的关系型数据库。

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » asp.net缓存要注意些什么?

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情