无标题文档

当前位置: / 首页 / 企业新闻 / 正文  
 
二十八条改善ASP性能的技巧。
 
目录 
技巧 1:将经常使用的数据缓存在 Web 服务器上 
技巧 2:将经常使用的数据缓存在 Application 或 Session 对象中
技巧 3:将数据和 HTML 缓存在 Web 服务器的磁盘上 
技巧 4:避免将非敏捷的组件缓存在 Application 或 Session 对象中 
技巧 5:不要将数据库连接缓存在 Application 或 Session 对象中
技巧 6:合理地使用 Session 对象
技巧 7:将代码封装在 COM 对象中 
技巧 8:迟一点获得资源,早一点释放资源 
技巧 9:进程外执行过程以性能换取可*性 
技巧 10:使用显式选项
技巧 11:在子例程和函数中使用局部变量 
技巧 12:将经常使用的数据复制到脚本变量中 
技巧 13:避免重新确定数组的维数 
技巧 14:使用响应缓冲 
技巧 15:批处理内嵌脚本和 Response.Write 语句 
技巧 16:如果页面需要很长时间才能完成,那么执行前使用 Response.IsClientConnected 
技巧 17:使用   标记例示对象 
技巧 18:对于 ADO 和其它组件使用 TypeLib 绑定 
技巧 19:利用浏览器的验证功能 
技巧 20:避免在循环语句中使用字符串串联 
技巧 21:启用浏览器和代理缓存 
技巧 22:尽可能使用 Server.Transfer 代替 Response.Redirect 
技巧 23:在目录 URL 中使用后斜杠 
技巧 24:避免使用服务器变量 
技巧 25:升级到最新和最出色的 
技巧 26:优化 Web 服务器 
技巧 27:进行性能测试 
技巧 28:阅读资源链接 

以上内容地址为:
http://www.microsoft.com/china/technet/iis/tips/ASPTIPS.asp

以下为部分内容:

技巧 2: 将经常使用的数据缓存在 Application 或 Session 对象中 
ASP Application 和 Session 对象为将数据缓存在内存中提供了方便的容器。您可以将数据指派到 Application 和 Session 对象中,这些数据在 HTTP 调用之间保留在内存中。Session 数据是按每个用户分别存储的,而 Application 数据则在所有用户之间共享。 

什么时候将数据装载到 Application 或 Session 中呢?通常,数据是在启动 Application 或 Session 时装载。要在 Application 或 Session 启动过程中装载数据,应将适当的代码分别添加到 Application_OnStart() 或 Session_OnStart() 中。这些函数应在 Global.asa 中,如果没有,则可以添加这些函数。还可以在第一次需要时装载该数据。为此,在 ASP 页中添加一些代码(或编写一个可重复使用的脚本函数),以检查数据是否存在,如果不存在,就装载数据。这是一个传统的性能技术,称为“惰性计算” - 在您知道需要某一个值以前不计算该值。例如: 

<%
Function GetEmploymentStatusList
Dim d
d = Application(?EmploymentStatusList?)
If d = ?? Then
' FetchEmploymentStatusList function (not shown)
' fetches data from DB, returns an Array
d = FetchEmploymentStatusList()
Application(?EmploymentStatusList?) = d
End If
GetEmploymentStatusList = d
End Function
%>


可以为所需要的每个数据块编写类似的函数。 

应以什么格式存储数据?可以存储任何变体类型,因为所有脚本变量都是变体型。例如,您可以存储字符串、整数或数组。通常,您将以这些变量类型之一存储 ADO 记录集的内容。要从 ADO 记录集获取数据,您可以手工将数据复制到 VBScript 变量,一次一个字段。使用一个 ADO 记录集持久函数 GetRows()、GetString() 或 Save()(ADO 2.5),可加快速度且更容易一些。其详细情况已超出本文所讨论的范围,但下面给出了一个函数举例,说明使用 GetRows() 返回记录集数据的一个数组: 

' Get Recordset, return as an Array
Function FetchEmploymentStatusList
Dim rs 
Set rs = CreateObject(?ADODB.Recordset?)
rs.Open ?select StatusName, StatusID from EmployeeStatus?, _
?dsn=employees;uid=sa;pwd=;?
FetchEmploymentStatusList = rs.GetRows() ? Return data as an Array
rs.Close
Set rs = Nothing
End Function


对上面举例做更进一步改进,可以将 HTML 缓存为列表,而不是数组。下面是简单的示例: 

' Get Recordset, return as HTML Option list
Function FetchEmploymentStatusList
Dim rs, fldName, s
Set rs = CreateObject(?ADODB.Recordset?)
rs.Open ?select StatusName, StatusID from EmployeeStatus?, _
?dsn=employees;uid=sa;pwd=;?
s = ?? & vbCrLf
Set fldName = rs.Fields(?StatusName?) ' ADO Field Binding
Do Until rs.EOF
' Next line violates Don't Do String Concats,
' but it's OK because we are building a cache
s = s & ? ? & vbCrLf
rs.MoveNext
Loop
s = s & ?? & vbCrLf
rs.Close
Set rs = Nothing ' See Release Early
FetchEmploymentStatusList = s ' Return data as a String
End Function


在适当的条件下,可以将 ADO 记录集本身缓存在 Application 或 Session 作用域中。有两个警告: 

必须将 ADO 标记为自由线程 
必须使用断开连接的记录集。 
如果不能保证满足这两个要求,则不要缓存 ADO 记录集。在下面的“非敏捷组件”和“不要缓存连接”技巧中,我们将讨论将 COM 对象存储在 Application 或 Session 作用域中的危险性。 

当您将数据存储在 Application 或 Session 作用域时,数据将保留在那里,直到您以编程方式改变它、Session 过期或 Web 应用程序重新启动为止。如果数据需要更新怎么办?要手工强制对 Application 数据进行更新,您可以访问只有管理员才可访问的 ASP 页来更新数据。或者,您可以通过函数定期自动刷新数据。下面例子存储带有缓存数据的时间戳,并隔一段时间后刷新数据。 

<%
' error handing not shown...
Const UPDATE_INTERVAL = 300 ' Refresh interval, in seconds

' Function to return the employment status list
Function GetEmploymentStatusList
UpdateEmploymentStatus
GetEmploymentStatusList = Application(?EmploymentStatusList?)
End Function

' Periodically update the cached data
Sub UpdateEmploymentStatusList
Dim d, strLastUpdate
strLastUpdate = Application(?LastUpdate?)
If (strLastUpdate = ??) Or _
(UPDATE_INTERVAL < DateDiff(?s?, strLastUpdate, Now)) Then

' Note: two or more calls might get in here. This is okay and will simply
' result in a few unnecessary fetches (there is a workaround for this)

' FetchEmploymentStatusList function (not shown)
' fetches data from DB, returns an Array
d = FetchEmploymentStatusList()

' Update the Application object. Use Application.Lock()
' to ensure consistent data
Application.Lock
Application(?EmploymentStatusList?) = Events
Application(?LastUpdate?) = CStr(Now)
Application.Unlock
End If
End Sub


请参见 World's Fastest ListBox with Application Data,上面还有一个例子。 

要知道在 Session 或 Application 对象中缓存大的数组不是一个好的做法。在访问数组的任何元素之前,脚本语言的语法要求必须临时复制整个数组。例如,如果将由字符串组成的有 100,000 个元素的数组(该数组将美国邮政编码映射到当地的气象站)缓存在 Application 对象中,ASP 必须先将所有的 100,000 个气象站复制到临时数组中,然后才能提取一个字符串。在这种情况下,用自定义方法建立一个自定义组件来存储气象站 - 或使用一个词典组件会更好。 

再警告大家一下,不要将婴儿与洗澡水一起倒掉:数组能快速查寻和存储在内存中是邻近的关键数据对。索引一个词典比索引一个数组要慢得多。应针对您的实际情况,选择提供最佳性能的数据结构。 

============================================
技巧 5:不要将数据库连接缓存在 Application 或 Session 对象中 
缓存 ADO 连接通常是很糟糕的策略。如果一个 Connection 对象存储在 Application 对象中,并在所有的页面中使用,那么所有页面将争抢这一连接。如果 Connection 对象存储在 ASP Session 对象中,那么将为每个用户创建数据库连接。这就会使连接池的优势荡然无存,并给 Web 服务器和数据库带来不必要的压力。 

可以不缓存数据库连接,而是在使用 ADO 的每个 ASP 页面中创建和删除 ADO 对象。这是很有效的,因为 IIS 内嵌了数据库连接池。更准确地说,IIS 自动启用 OLEDB 和 ODBC 连接池。这就能确保在每个页面上创建和删除连接将是有效的。 

因为连接的记录集存储一个到数据库连接的引用,所以您不应将连接的记录集缓存在 Application 或 Session 对象中。但是,您可以安全地缓存断开连接的记录集,它们不保存到其数据连接的引用。要断开记录集连接,执行下面的两个步骤: 

Set rs = Server.CreateObject(?ADODB.RecordSet?)
rs.CursorLocation = adUseClient ' step 1

' Populate the recordset with data
rs.Open strQuery, strProv

' Now disconnect the recordset from the data provider and data source
rs.ActiveConnection = Nothing ' step 2


有关连接池的更详细信息,可以在 ADO 和 SQL Server 参考资料中找到。 

===================================================

技巧 6:合理地使用 Session 对象 
既然我们已经讨论了缓存在 Application 和 Session 中的优点,现在开始讨论避免使用 Session 对象的问题。正如下面所讨论的,当与忙的站点一起使用时,Session 有几个缺点。“忙”的意思一般是指一秒钟要求几百页面或成千上万同时用户的站点。这个技巧对于必须水平扩展的站点 - 即,那些利用多台服务器以处理负载或实现容错的站点 - 甚至更重要。对于较小的站点,诸如 Intranet 站点,要想实现 Session 带来的方,必然增大系统开销。 

简言之,ASP 自动为每个访问 Web 服务器的用户创建一个 Session。每个 Session 大约需要 10 KB 的内存开销(最主要的是数据存储在 Session 中),这就使所有的请求都减慢。在配置的超时时段(通常是 20 分钟)结束以前,Session 一直保留有效。 

Session 的最大的问题不是性能,而是可扩展性。Session 不能跨越几台 Web 服务器,一旦在一台服务器上创建 Session,其数据就留在那儿。这就意味着如果您在一个 Web 服务器群使用 Session,您必须设计一个策略,将每个用户请求始终发到用户 Session 所在的那台服务器上。这被称为将用户“粘”在 Web 服务器上。术语“粘性会话”就是从这里派生而来的。如果 Web 服务器崩溃,被“粘住的”用户将丢失他们的会话状态,因为会话不是粘到磁盘上。 

实现粘性会话的策略包括硬件和软件解决方案。诸如 Windows 2000 Advanced Server 中的网络负载平衡和 Cisco 的 Local Director 之类的解决方案都可以实现粘性会话,代价是要损失一定程度的可扩展性。这些解决方案是不完善的。不建议此时部署您自己的软件解决方案(我们过去常常使用 ISAPI 筛选器和 URL 转换等等)。 

Application 对象也不跨越多台服务器,如果您必须跨越 Web 服务器群共享和更新 Application 数据,您必须使用后端数据库。但是,只读 Application 数据在 Web 服务器群中仍是有用的。 

如果只是因为要增加运行时间(处理故障转移和服务器维护),大多数关键任务站点至少需部署两台 Web 服务器。因此,在设计关键任务应用程序时,必须实现“粘性会话”,或干脆避免使用 Session,以及任何其它将用户状态存储在单个 Web 服务器上的状态管理技术。 

如果您不使用 Session,一定要将它们关闭。您可以通过 Internet Services Manager,为应用程序执行此操作(参见 ISM 文档)。如果您决定使用 Session,您可以采用一些方法减轻它们对性能的影响。 

您可以将不需要 Session 的内容(如帮助屏幕,访问者区域等等)移到另一个关闭了 Session 的 ASP 应用程序中。您可以逐页提示 ASP,您不再需要该页面上的 Session 对象,使用以下放在 ASP 页面最上面的指令: 

<% @EnableSessionState=False %>


使用这一指令有一个很好的理由是,这些 Session 在框架集方面存在一个有意思的问题。ASP 保证任何时候 Session 只有一个请求执行。这样就确保如果浏览器为一个用户请求多个页面,一次只有一个 ASP 请求接触 Session,这样就避免了当访问 Session 对象时发生的多线程问题。很遗憾,一个框架集中的所有页面将以串行方式显示,一个接一个,而不是同时显示。用户可能必须等候很长时间,才能看到所有的框架。该故事的寓意:如果某些框架集页面不依* Session,一定要使用 @EnableSessionState=False 指令告诉 ASP。 

有许多管理 Session 状态的方法,可替代 Session 对象的使用。对于少量的状态(少于 4 KB),我们通常建议使用 Cookies、QueryString 变量和隐式变量。对于更大数据量,如购物小车,后端数据库是最适合的选择。有关 Web 服务器群中状态管理技术的文章很多。有关详细信息,请参见 Session 状态参考资料。

===============================================
技巧 10:使用显式选项 
在 .asp 文件中应使用 Option Explicit。此指令放在 .asp 文件的最上面,它强制开发人员声明要使用到的所有变量。许多程序员认为这种方法对于调试应用程序很有帮助,因为这种方法避免了键错变量名和误建新变量的可能性(例如,将 MyXMLString=) 错写成 MyXLMString=...。 

更重要的一点也许是,声明的变量比未声明的变量速度更快。由此,脚本在运行时每次用到未声明的变量时,按名称引用它。另一方面,声明的变量是有顺序的,要么以编译时间,要么以运行时间。以后,声明的变量都按此顺序引用。因为 Option Explicit 强制变量声明,它能确保声明所有变量,因此访问的速度也很快。 




 

地址:广东省佛山市三水区货场路19号 邮编:528100
客服电话:0757-87732643 电子邮箱:fengshun@ssfengshun.cn
三水丰顺食品有限公司版权所有 2008

 

丰顺食品有限公司