技巧 3:将数据和 html 缓存在 web 服务器的磁盘上
有时,数据可能太多,无法都缓存在内存中。“太多”只是一个说法,这要看您想消耗多少内存,以及需缓存的项目数和检索这些项目的频率。在任何情况下,如果数据太多而无法都缓存在内存中,则考虑将数据以文本或 xml 文件缓存在 web 服务器的硬盘上。可以同时将数据缓存在磁盘和内存中,为您的站点建立最适宜的缓存策略。
注意当测量单个 asp 页的性能时,检索磁盘上的数据可能不一定要比从数据库检索数据更快。但缓存会降低数据库和网络上的负载。在高负载的情况下,这样做可大大改善总体吞吐量。当缓存开销很大的查询结果(如多表联接或复合存储过程)或大的结果集时,这是非常有效的。与往常一样,要测试一下几种方案的优劣。
asp 和 com 提供一些建立基于磁盘的缓存方案的工具。ado 记录集 save() 和 open() 函数保存和装载磁盘中的记录集。可以使用这些方法重新编写上面 application 数据缓存技巧中的代码示例,用文件的 save() 代替写到 application 对象中的代码。
有一些其它组件可以用于文件:
scripting.filesystemobject 可使您创建、读和写文件。
与 inte.net explorer 一起提供的 microsoft® xml 解析器 (msxml) 支持保存和装载 xml 文档。
lookuptable 对象(例如,用在 msn 上)是从磁盘装载简单列表的最好选择。
最后,应考虑将数据的表示缓存在磁盘上,而不是数据本身。预先转换的 html 可以用 .htm 或 .asp 文件存储在磁盘上,超级链接可以直接指向这些文件。可以使用商用工具,如 xbuilder,或 microsoft® sql server™ inte.net 发布功能将产生 html 的过程自动化。或者,您可以将 html 代码片断放在 .asp 文件中。还可以使用 filesystemobject 从磁盘读取 html 文件,或使用 xml 尽早转换。
技巧 4:避免将非敏捷的组件缓存在 application 或 session 对象中
尽管将数据缓存在 application 或 session 对象中是一个好的做法,但缓存 com 对象却有严重的陷阱。通常,人们倾向于将经常使用的 com 对象缓存到 application 或 session 对象中。很遗憾,许多 com 对象(包括所有以 visual basic 6.0 或更低版本编写的对象)当存储在 application 或 session 对象时,会引起严重的瓶颈。
具体来讲,当任何不敏捷的组件缓存在 session 或 application 对象时,将引起性能瓶颈。敏捷的组件是被标记为 threadingmodel=both 的组件,它聚集 free-threaded marshaler (ftm);或被标记为 threadingmodel=neutral 的组件。(neutral 模型是 windows® 2000 和 com+ 的新增模型。) 下列组件不是敏捷的:
自由线程的组件(除非它们聚集 ftm)。
单元线程组件。
单线程组件。
配置的组件(microsoft transaction server (mts)/com+ 库和服务器程序包/应用程序)不是敏捷的,除非它们是 neutral 线程。单元线程组件和其它非敏捷的组件在页作用域内是最适合的(即,它们在单个 asp 页上创建和销毁)。
在 iis 4.0 中,被标记为 threadingmodel=both 的组件被认为是敏捷的。在 iis 5.0 中,只有这一点还不够。组件必须不仅被标记 both,还必须聚集 ftm。有关敏捷性的文章讲述了如何使以 active template library 编写的 c++ 组件聚集 ftm。要注意如果组件缓存界面指针,那么那些指针本身必须是敏捷的,或必须存储在 com 共用界面表 (git) 中。如果您不能重新编译 both 线程组件以聚集 ftm,那么您可以将组件标记为 threadingmodel=neutral。或者,如果您不想让 iis 执行敏捷性检查(因此,您可以允许非敏捷的组件存储在 application 或 session 作用域中),您可以在配置数据库中将 asptrackthreadingmodel 设置为 true。不建议更改 asptrackthreadingmodel。
如果您想将以 server.createobject 创建的非敏捷的组件存储在 application 对象中,iis 5.0 将出现一个错误。您可以在 global.asa 中使用 <object runat=server scope=application ...> 避免这一错误,但不建议这样做,因为这会导致汇集和串行化,关于这一点将在下面讲述。
如果您缓存非敏捷的组件会出现什么毛病?缓存在 session 对象中的非敏捷的组件将 session 锁定于 asp 工作者线程。asp 维护一个工作者线程池来处理请求。通常情况下,一个新请求总是由第一个可用的工作者线程来处理。如果 session 被锁定于一个线程,那么请求必须等到其相关的线程可用为止。这里有一个类比,也许会有所帮助:您去一家超级市场,挑选了一些商品,并在 #_3 收款台付款。其后,每当您在那家超级市场为商品付款时,您总是必须在 #_3 收款台付款,即使其它收款台前排队的人较少或者没有人排队,也是如此。
将非敏捷的组件存储在 application 作用域对性能的影响甚至更坏。asp 必须创建一个特殊的线程运行存储在 application 作用域中的非敏捷组件。这会有两个结果:所有调用都必须汇集到此线程,且所有调用都排成长队。“汇集”的意思是参数必须存储在内存的共享区域;执行一个开销很大的到特殊线程的上下文切换;执行组件的方法;将结果汇集到共享区域;执行另一个开销很大的上下文切换,将控制返回到原始的线程。“串行化”意思是指每次只运行一个方法。两个不同的 asp 工作者线程不能同时在共享组件上执行多个方法。这样就杜绝了并发性,特别是在多处理器计算机上。更糟的是,所有非敏捷的 application 作用域的组件共享一个线程(主机 sta),因此串行化的影响甚至更显著。
如之奈何?下面是一些一般的规则。如果您使用 visual basic (6.0) 或更早版本编写对象,那么不要将它们缓存在 application 或 session 对象中。如果您不知道对象的线程模型,不要缓存它。不要缓存非敏捷的对象,而应在每个页面创建和释放它们。对象直接在 asp 工作者线程上运行,因此没有汇集或串行化。如果 com 对象在 iis 服务器上运行,且如果它们不花长时间初始化和删除,性能尚可。注意单线程对象不应该这样使用。小心 - vb 可创建单线程对象!如果您必须这样使用单线程对象(如 microsoft excel 电子表格),别指望会有很高的吞吐量。
当 ado 被标记为自由线程,ado 记录集可以安全地缓存。要将 ado 标记为自由线程,使用 makfre15.bat 文件,该文件通常位于目录 \\program files\common\system\ado 中。
警告 如果您使用 microsoft access 作为数据库,不应将 ado 标记为自由线程的。ado 记录集也必须切断连接。一般来说,如果您不能控制站点中的 ado 配置(例如,您是一个独立的软件厂商 [isv],向管理他们自己的配置客户销售 web 应用程序),最好不要缓存记录集。
词典组件也是敏捷的对象。lookuptable 从数据文件中装载其数据,可用于组合框数据和配置信息。duwamish books 中的 pagecache 对象可提供词典语法,caprock dictionary 也可提供。这些对象或其派生对象可以构成有效缓存策略的基础。注意 scripting.dictionary 对象不是敏捷的,不应该存储在 application 或 session 作用域中。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器