您现在的位置是:首页 > .NET

.NET

页面静态化与asp.net缓存机制对比的精彩讨论

2020-11-20 10:39:16 .NET admin
问题:假如有100万个页面,每天有5%的页面会浏览十次以上,有50%的页面只浏览一次,剩下45%没人看过。这种情况下是使用页面静态化处理好,还是使用asp.net的缓存功能好。以下回复均来自csdn中牛人们的讨论,粘贴如下,很值的我们学习与
问题:假如有100万个页面,每天有5%的页面会浏览十次以上,有50%的页面只浏览一次,剩下45%没人看过。这种情况下是使用页面静态化处理好,还是使用asp.net的缓存功能好。

以下回复均来自csdn中牛人们的讨论,粘贴如下,很值的我们学习与参考。各讨论间使用--分隔开,使用[]括起来的表示是引用其他人的回复。

静态页面众所周知是以空间换时间.当然这也是一个代价
缓存功能很有效的降低网络的耗损,其他客户机在访问该网站的时候也会通过局域网内的缓存获取数据降低了服务端本身的压力
-----------------------------------------------------------------------

静态页面除了以空间换时间,还有一定的IO损耗,并发量特别大的情况下完全采用静态页面也不是好的解决方法,例如你所提到的假如有100万个页面,甚至更多,每天,有5%的页面会浏览十次以上,有50%的页面只浏览一次。剩下45%根本没人看过。要我选择的话,在保证这些页面基本不怎么变动的话,我会将这5%的页面在程序初始的加入缓存,将50%的页面在第一次读取的时候加入缓存,剩下的作为静态页面储存。
可以建立一个静态的类,里面就2个属性,一个页面路径,一个访问次数,记录每个页面的请求信息,然后重载IHttpHandler,在此进行处理,我可以根据上述静态类所提供的信息
,来决定缓存策略
-----------------------------------------------------------------------

(1)从安全角度出发,静态页面是安全的。
(2)正如楼主所说,在定期限内效率较态页面高,但假如有100万个页面,甚至更多,每天,有5%的页面会浏览十次以上,有50%的页面只浏览一次。剩下45%根本没人看过。应该综合权衡一下,适当的静态化5%的页面,可以考虑用MS自带缓存;那50%的页面如果是并发访问,就得交给数据库服务器完成,建立索引,用户查询时动态的生成,oracle这方面比较棒。
(3)实际使用中,效率和安全稳定第一位。
-----------------------------------------------------------------------

引用楼主iuhxq的帖子:
[另外我有个疑问,用缓存时,如果内存不够了怎么办?是用硬盘存放,还是释放缓存?]
成熟的缓存系统关键就是它会智能地丢弃缓存的内容,而这个“丢弃”的时机是经过千锤百炼,要比你在自己的代码中使用内存方式通常要更适合服务器内存实际情况。

至于功能,就更无法比拟了。

缓存系统的主要特征是提供了各种灵活的Dependecy,不但内存达到一定条件(默认是60%),时间达到一定条件(产生之后的时间、最后访问时间),还可以依赖于文件改变、数据库改变,甚至自己编写缓存依赖条件,这是关键。

关键是对于交互式网站还需要大量使用“片段缓存”。

我没有一棍子打死“静态页面”做法,对于很简单的无交互网站当然可以。我要强调的是如果你的handler仍然是asp.net的,网页链接还是asp.net方式的,如果删除网站的
asp.net系统之后静态页面就不能从网站上正常导航到了,那种“静态页面”网站相对来说你当初就不应该使用asp.net这种过分高级的工具开发。
-----------------------------------------------------------------------

我觉得静态页面只适合于访问量大,并且静态页面数量小的情况
当一个文件夹下面有几千个静态文件的时候,效率呈级数下降
所谓容易被搜索引擎检索到,动态页面做成伪静态页面也可以的
都存到数据库里,用户访问的时候生成静态页,访问静态页的时候通过脚本更新最后访问时间
然后用WINDOWS服务来决定哪些访问量小的页面要删除
-----------------------------------------------------------------------

引用楼主iuhxq的帖子:
[假如有100万个页面,甚至更多,每天,有5%的页面会浏览十次以上,有50%的页面只浏览一次。剩下45%根本没人看过。]
实际上,这正是说明为什么有很多公司使用asp.net原因。asp.net是动态网站生成工具,你越是发掘动态交互网站的能力时(例如用户自己选择theme),你才越是需要asp.net。
“100万个页面”其实可能只是从20个aspx中动态产生的。asp.net缓存是内置在动态交互网站上已经成熟的技术,你不需要纠缠于是否需要把整个网站导出以及导出之后带来的一切“动态”问题,直接在asp.net程序本身的优化升级过程中轻松搞定,提高性能的同时没有丧失任何动态特征,在网站性能升级过程中丝毫没有“成事不足败事有余”之感,何乐而不为。
使用asp.net的关键是会设置最恰当的“缓存依赖条件”。我看到很多人仅会设置Duration参数,这可能是“滥用缓存”或者“不用缓存”的原因。要恰好让依赖的数据改变时缓存立刻失效,而依赖的数据没有改变时要千方百计地优先使用缓存,才能提高网站性能。
-----------------------------------------------------------------------

其实过多使用asp.net缓存问题相当严重,真正使用过的就会发现它最严重的问题并不在于它的服务器内存够不够的问题,这虽然是一个方面,但不是最重要的。
第一个问题:相当严重的缓存过期问题,改动一个dll,改动下配置文件,改变下code立刻很使所有缓存被重置,服务器刚开始本来就需要大量的CPU的时间来对dll进行编译,然后再大量的SQL查询,然后再频繁的内存释放和重分配,相当的致命,再之后的相当长时间内服务器会运行迟缓,毕竟所有的缓存都要在遇到访问时重新进行SQL查询,然后重新定义。
第二个问题:服务器缓存的过期问题,页面缓存的过期确实有时候并没有按照预想的时候进行过期,提早的可能性很大,可以声明的事这并不是内存不够的问题。然后就是没有过期的问题,好像感觉上没有可能,其实可能性很大,服务器的页面缓存大多数都是进行文件依赖的,这个文件依赖交错错中复杂,确并不是100%可靠。
因此不要过于依赖于asp.net的缓存机制,我宁可你把这种机制建立在第三方的缓存方案上。
至于做静态页可能遇到相当多的静态页面,其实只要你选择了这种方案,如果是遇到百万级的静态页面,那肯定是有相应的机制来控制这种的静态页的生存期,而这种机其实相当简单,这种考虑是多虑了,就如同控制IIS的日志增长一样,谁会放任不管的?
-----------------------------------------------------------------------

引用19楼iuhxq的回复:
[我在想,一个页面可能依赖几个表(数据库),一个表可能被多个页面依赖。也可以说成是多对多的关系。如何让这些改变能立刻生效,需要深入研究才能搞清楚。我目前对这个还是比较模糊。没有成功]

如果明知道一个页面很少使用,首先是没有必要缓存。

其实,我从来不用页面缓存,我都是片段缓存的。当然我不反对页面缓存,而是对我来说用户控件才是编程核心,页面都是很简单的,几乎10秒钟创建一个页面,剩下的功夫就是把以前做好的用户控件添加其中并设置它们之间数据协调一致。

关于数据库表更新问题,可以参考有关页面缓存管理中的SqlDependency资料。

也可以简单一些。我在那个“如何看你的缓存是否生效”的帖子中写的例子里是根据cookie来刷新缓存,当然你可以改为返回数据表中的某个“时间戳”的值。例如一个“用户订单”的界面(不是指订单细节,而是指订单的头部信息),你在数据库中可以为这个“订单”表增加一个“最后修改时间”字段以及增加一个触发器来产生这个字段值,这样订单界面在用户录入细节内容时它的头部信息部分可以作为一个独立的ascx,当用户编辑订单细节时订单头部实际上并不重建控件。你在订单界面上可以用代码输出订单头部用户控件的对象,你会发现它大多数时候是null,也就是说当编辑订单细节时订单头部控件“根本不存在”,asp.net只是从缓存中拿出html直接输出。既然根本没有重建用户控件,当然不会去读数据库。
-----------------------------------------------------------------------

引用19楼iuhxq的回复:
[刚才你提到,对于不常访问的的页面,让他缓存失效,但是我举的例子里有50%页面可能每天访问一次,这样你要不停的缓存、失效。从逻辑上说,也比较走弯路。不如静态页面,一直放那里好。]

一种情况是确实是1个小时也难得有一个访问,可能是根本无需缓存。这类页面即使不缓存,也没有什么损失。

另一种是你完全可以缓存较长时间,例如缓存1个小时。是不是缓存缓存时间越长就代表优先级越高?显然不是。如果内存不足,任何不常用的东西首先被从内存删除,跟你设置的Duration无关。因此,如果你设置缓存1个小时,然后它在1个小时后某个时间点被asp.net在千分之一秒内删除了,即使这期间没有一个请求访问过缓存的页面,花费千分之一秒时间代价也无所谓。如果你设置为缓存10秒钟,但是通常在10秒钟内不足够有一个请求访问它,这个代价才不值得缓存。我们可以看见,如果缓存不值得,首先的考虑可以是加大缓存时间,例如从10秒钟变为30秒钟、1分钟、5分钟、20分钟、1小时。当很大的缓存时间还是觉得不值得,才根本取消缓存。如果又希望避免重建控件内容,又害怕“不停的缓存、失效”,这其实是自相矛盾的。关键是:1:设置了缓存时间只是最低级的缓存策略,必须同时配合业务要求来控制缓存及时失效;2:相信不论你如何设置缓存依赖条件,缓存系统都会优先根据服务器内存使用情况来自己决定是否提前清理缓存的对象,因此尽量使用缓存并不会造成服务器内存实际的故障。
-----------------------------------------------------------------------

引用23楼zhujiechang的回复:
[第一个问题:相当严重的缓存过期问题,改动一个dll,改动下配置文件,改变下code立刻很使所有缓存被重置,服务器刚开始本来就需要大量的CPU的时间来对dll进行编译,然后再大量的SQL查询,然后再频繁的内存释放和重分配,相当的致命,再之后的相当长时间内服务器会运行迟缓,毕竟所有的缓存都要在遇到访问时重新进行SQL查询,然后重新定义。]

这其实根本不是缓存过期,而是网站更新,整个进程重新启动。什么时候网站必须更新?如果你生成了一堆静态页面,但是网站必须重新更新,此时那些静态页面能够幸免被重建的命运吗?如果能够幸免,也就无需重新更新网站程序。
-----------------------------------------------------------------------

引用23楼zhujiechang的回复:
[第二个问题:服务器缓存的过期问题,页面缓存的过期确实有时候并没有按照预想的时候进行过期,提早的可能性很大,可以声明的事这并不是内存不够的问题。然后就是没有过期的问题,好像感觉上没有可能,其实可能性很大,服务器的页面缓存大多数都是进行文件依赖的,这个文件依赖交错错中复杂,确并不是100%可靠。]

我最头疼的就是很多人把asp.net的缓存机制说成是“定时保存”对象,这是一种很“坏”的歪曲。Duration时间是我们给缓存一个最低级、最基础的约束,然后我们就必须给它一个业务需要的“适时失效”约束。把缓存理解成为在内存中以一段固定的时间占用内存,这是很偏的,造成了滥用缓存或者不用缓存的结果。

我记忆中很难想起哪一个是不得不进行文件依赖的!除非逻辑上本来就是依赖这个文件,否则丝毫无需用文件依赖。
另外,文件依赖仅需要设置一个文件路径字符串而已,并不是错综复杂。真正造成错综复杂的,可能使在逻辑上根本无需文件依赖的时候一定要将许多其它数据改变导成文件依赖这个结果上。这其实查找技术的问题。缓存还是很简单的,只是你找到的资料少,可能不像介绍GridView控件的资料那样地泛滥而已。
-----------------------------------------------------------------------

除了我的页面都是用户控件组合而成之外(至少我可以在一个页面上仅放一个用户控件,当然至今还不会使用masterpage),不使用页面缓存的理由还包括很重要的:UpdatePanel不支持。这很自然,整个页面缓存了,UpdatePanel的事件就无法触发。

但是片段缓存完全支持UpdatePanel。
-----------------------------------------------------------------------

引用31楼only_endure的回复:
[如何自已编写缓存依赖条件呢?
我看到的书上写的是在数据源控件的声明语句里,加上某属性.实现数据依赖(根据数据表格中某个字段或某条记录),是用声明语句写的.很生硬.]

我举了一个例子:
http://topic.csdn.net/u/20080428/16/3d1fe832-b328-49b4-9a54-d193e3e03a17.html

VaryByParam、VaryByControl等的例子网上有很多。

实际上,如果使用Page.LoadControl来动态加载用户控件,要知道PartialCachingControl这个对象(类)的编程。它的CachePolicy属性可以调用缓存api,它的Dependency属性可以接受你自定义的Dependency。

网上也有一些自定义缓存依赖对象的文章,就是从CacheDependency类继承并写自己的控制代码。这些文章中文的可能不太多。

不过我写的那个例子其实已经很够用了,加入一些数据控制的代码来获得正在处理的ascx的对象的信息,就能达到大多数asp.net性能优化的要求。

注意一点,我在网上读过这样的文章,它把数据表保存到Session中,然后大谈在什么逻辑下用代码去从Session中删除数据表。它把这个叫做缓存!我所说的asp.net绝非这种编程,而是指asp.net自身(原生)的缓存。如果把数据表放到Cache中,当内存不足时缓存系统会自动删除它。因此Session集合不是缓存,asp.net的数据缓存集合是指Cache集合而不是Session集合。asp.net进程重启也不是缓存刷新,整个进程都重启了,缓存当然不见了,但是进程重启并不是缓存系统可以决定的事情。
-----------------------------------------------------------------------

静态页和缓存的对比,这是个很“搞笑”的问题,因为静态页就是一种缓存方案!所谓静态页,就是把原本要执行才能显示的页面,再有执行需求之前先执行一次,将结果以文件形式缓存到硬盘,这难道不是缓存?

内存不足是不是缓存到硬盘,这当然是的。硬盘不足还可以缓存到磁带呢,不过效率又是另一个问题。

总的来说,存储器越快的就越贵,因此速度快的存储器容量自然越少,因此必然要把内容“缓存”到更大的但更慢的存储器上,从CPU的寄存器到CPU的高速缓存,再到内存和硬盘,每一个级别都如此。真正的问题是,怎样的缓存策略是有效的。静态页是一个特定的缓存策略,很多时候反对盲目追求静态页,是因为对大多数人来说这种策略都是不适用的,就这么简单。
-----------------------------------------------------------------------

IIS默认是可以对静态页面进行直接访问的,如果是动态页面,IIS会调用相应的handler来处理。这是需要一定开销的,但是如果缓存技术的引入,那么这种开销就小得多了。

至于静态页面的访问涉及到文件的IO,我觉得,这就要比较fat32,NTFS等文件系统的定位速度和数据库的定位速度哪个更快一些!!

缓存是程序设计中至关重要的一点!听说hiberante都有二级缓存了,听了后吓我一跳,仔细一问原来就是和全局缓存差不多。不是以速度取胜,而是以缓存的时间更长、范围更大来取胜!
-----------------------------------------------------------------------

如果数据量大并且访问量大,我感觉还是静态页面的好。而且纯静态的最好了。就是不经过.net处理的页面。直接从IIS发送给客户端。

因为这么做,可以避免“缓存”“失效”“缓存”“失效”这种重复的过程。尤其一个网站中,实际上,大量的页面,一天只浏览一两次,这时你要是给他缓存了,那没等有下一个人来访问呢,缓存就失效了,相当于,缓存的利用率(也可以说是命中率)不高。

另外,如果有几万甚至更多的页面,这些放内存里缓存根本放不下,必然会因为内存占用过高导致释放内存(也可能是把内存中的数据写入硬盘,缓存了,如果是写入硬盘了,首先他不能无限的写入,有个1,2个G足够大了,不能写入10G,20g这么多。也就是说还是有一大部分页面被从缓存中移除了。)总的说来,还是直接生成静态页面,放硬盘上比较稳定。

当然,以上都是考虑页面变化不频繁的情况。如果真的如SP1234所说,每个登录用户看到的页面都是个性的。那就只能动态处理结合片段缓存
-----------------------------------------------------------------------

页面静态化和系统缓存各有优势,准确的说系统缓存的确是要比静态化页面更高级一点,因为系统缓存是将数据缓存到内存中,而页面静态化是将数据以文本的形态存储在硬盘中。

在楼主的问题中提到了这样一个假设的情况:
假如有100万个页面,甚至更多,每天,有5%的页面会浏览十次以上,有50%的页面只浏览一次。剩下45%根本没人看过。

我想说针对于这样一种情况我们就不能单纯的来考虑到底是用系统缓存还是用页面静态化,如果全部用系统缓存的话我们担心内存不够,如果全部用页面静态化又担心I/O过高,硬盘读写过于频繁。所以针对于这两种问题我觉得我们应该将页面静态化和系统缓存结合起来使用,我们可以将5%的数据缓存到内存中(使用系统缓存),将45%和50%的数据静态化。
例如Squid这个组件就是将html文件缓存到内存中。Squid在PHP里面经常用到。
-----------------------------------------------------------------------

我们不去计较以上各位牛人的解理谁对谁错,对于还没有迈入牛人行列的我们,好好理解就行了。jv^怱_衏貧penc揯YBg'`亯詋:_6Ro甆剉penc揯緥v^O(u彇a剉-N魰B\}Y坃Y0<