开发高性能的 ASP.NET 应用程序

使用本主题中的准则所列出的方法有助于最大程度提高 ASP.NET Web 应用程序的吞吐量。这些准则分为以下部分:

  •  

  • Web 应用程序

    下列准则提供了使整个 Web 应用程序有效工作的建议。

    • 考虑预编译 在对资源(如 ASP.NET 网页)的首次请求中,Web 应用程序是批编译的。如果应用程序中的页都没有编译,批编译功能会成批编译目录中的所有页,以增加磁盘和内存的使用率。可以使用 ASP.NET 编译工具 (Aspnet_compiler.exe) 预编译 Web 应用程序。对于就地编译,该编译工具调用 ASP.NET 运行库来编译站点,其方式与用户向网站请求页时的方式相同。可以预编译 Web 应用程序,以便保留 UI 标记;也可以预编译页,以便不能更改源代码。有关更多信息,请参见How to: Precompile ASP.NET Web Sites

    如何:预编译 ASP.NET 网站

  • 在 Internet 信息服务 5.0 上,在进程外运行 Web 应用程序 默认情况下,IIS 5.0 上的 ASP.NET 将使用进程外辅助进程为请求提供服务。此功能已被优化以提高吞吐量。由于在进程外的辅助进程中运行 ASP.NET 有其功能和优点,建议在生产站点上使用它。

  • 定期回收进程 为了同时保证稳定性和性能,应该定期回收进程。经过较长的时间,有内存泄漏和 Bug 的资源可以影响 Web 服务器的吞吐量,而回收进程可以清理内存避免这类问题。但是,应当平衡定期回收的需求和过频的回收,因为停止辅助进程、重新加载页面并重新获取资源和数据的开销可能会超过回收的好处。

    在使用 IIS 6.0 的 Windows Server 2003 上运行的 ASP.NET Web 应用程序不需要调整进程模型设置,因为 ASP.NET 将使用 IIS 6.0 进程模型设置。

  • 必要时调整应用程序每个辅助进程的线程数 ASP.NET 的请求结构试图在执行请求的线程数和可用资源之间达到一种平衡。该结构将根据可用于请求的 CPU 功率,来决定允许同时执行的请求数。这项技术称作线程门控。但是在某些条件下,线程门控算法不是很有效。通过使用与“ASP.NET Applications”性能对象关联的“Pipeline Instance Count”(管线实例计数)性能计数器,可以在 Windows 性能监视器中监视线程门控。

    当 ASP.NET 网页调用外部资源时(例如执行数据库访问或 XML Web services 请求时),页面请求通常停止并释放 CPU 以处理其他线程,直到外部资源响应为止。如果另一个请求正在等待处理,并且线程池中有一个线程释放,则开始处理这个正在等待的请求。这可能导致 ASP.NET 辅助进程或应用程序池中存在大量同时执行的请求和许多正在等待的线程,而它们会影响 Web 服务器的吞吐量,从而对性能产生不利的影响。

    为缓解这种情况,可以通过更改 Machine.config 文件的 processModel 节中的 MaxWorkerThreads 和 MaxIOThreads 属性,手动设置对进程中的线程数的限制。

    注意:

    辅助线程是用来处理 ASP.NET 请求的,而 IO 线程则是用于为来自文件、数据库或 XML Web services 的数据提供服务的。

    分配给进程模型属性的值是进程中每个 CPU 每类线程的最大数目。对于双处理器计算机,最大数是设置值的两倍。对于四处理器计算机,最大值是设置值的四倍。对于有一个或两个处理器的计算机,默认值就可以,但对于有两个以上处理器的计算机的性能,进程中有 100 或 200 个线程则弊大于利。因为额外的上下文交换导致操作系统将 CPU 周期花在维护线程而不是处理请求上,所以进程中有太多线程往往会降低服务器的速度。线程适当的数目最好通过应用程序的性能测试来确定。

  • 对于广泛依赖外部资源的应用程序,请考虑在多处理器计算机上启用网络园艺 ASP.NET 进程模型帮助启用多处理器计算机上的可伸缩性,方法是将工作分发给多个进程(每个 CPU 一个),并且每个进程都将处理器关联设置为一个 CPU。此技术称为网络园艺。如果应用程序使用较慢的数据库服务器或调用具有外部依赖项的 COM 对象(这里只是提及两种可能性),则为您的应用程序启用网络园艺是有益的。但是,在决定对生产网站启用网络园艺之前,您应该测试应用程序在网络园中的执行情况。

  • 禁用调试模式 在部署生产应用程序或进行任何性能测量之前,始终禁用调试模式。如果启用了调试模式,应用程序的性能可能受到影响。有关设置调试模式的语法信息,请参见编辑 ASP.NET 配置文件

  • 优化 Web 服务器计算机和特定应用程序的配置文件以符合您的需要 默认情况下,ASP.NET 配置被设置成启用最广泛的功能集并尽量适应最常见的情况。可更改某些默认配置设置以提高应用程序的性能,具体取决于您使用的功能。下面的列表包含您应考虑的配置设置:

    • 仅对需要的应用程序启用身份验证 默认情况下,ASP.NET 应用程序的身份验证模式为 Windows 或集成的 NTLM。大多数情况下,最好仅对需要身份验证的应用程序在 Machine.config 文件中禁用身份验证,并在 Web.config 文件中启用身份验证。

    • 根据适当的请求和响应编码设置来配置应用程序 ASP.NET 默认编码格式为 UTF-8。如果您的应用程序仅使用 ASCII 字符,请配置您的 ASCII 应用程序以获得稍许的性能提高。

    • 考虑对应用程序禁用 AutoEventWireup 在 Machine.config 文件中将 AutoEventWireup 属性设置为 false,意味着页面不会将页事件绑定到基于名称匹配的方法(例如 Page_Load)。如果禁用 AutoEventWireup,页面将通过将事件连接留给您而不是自动执行它,获得稍许的性能提升。

      如果想要处理页事件,可以使用两种策略之一。第一种策略是重写基类中的方法。例如,可以为页加载事件重写 Page 对象的 OnLoad 方法,而不是使用 Page_Load 方法。(务必调用基方法以确保引发所有事件。)第二种策略是使用 Visual Basic 中的 Handles 关键字或 C# 中的委托连接来绑定到事件。

    • 从请求处理管线中移除不用的模块 默认情况下,服务器计算机的 Machine.config 文件中 HttpModules 节点的所有功能均保留为活动状态。根据应用程序所使用的功能,您可以从请求管线中移除不用的模块以获得稍许的性能提升。检查每个模块及其功能,并按您的需要自定义它。例如,如果您在应用程序中不使用会话状态和输出缓存,则可以从 HttpModules 列表中移除它们,以便请求在不执行其他有意义的处理时,不必调用这些模块。

编码实践

下列准则提供了编写有效代码的建议。

  • 不要依赖代码中的异常 异常会大大地降低性能,所以您应该避免将它们用作控制正常程序流的方式。如果有可能检测到代码中可能导致异常的状态,请执行这种操作,而不要捕捉异常本身和处理该状态。常见的代码检测方案包括:检查 null,将一个值分配给将分析为数值的 String,或在应用数学运算前检查特定值。下面的示例演示可能导致异常的代码以及测试是否存在某种状态的代码。两者产生相同的结果。

    C# “复制”图像复制代码
    // This is not recommended.
    try {
       result = 100 / num;
    }
    catch (Exception e) {
      result = 0;
    }
    
    // This is preferred.
    if (num != 0)
       result = 100 / num;
    else
      result = 0;

     

    Visual Basic “复制”图像复制代码
    ' This is not recommended.
    Try
       result = 100 / num
    Catch (e As Exception)
      result = 0
    End Try
    
    ' This is preferred.
    If Not (num = 0)
       result = 100 / num
    Else
      result = 0
    End If
  • 在托管代码中重写调用密集型的 COM 组件 .NET Framework 提供了一个简单的方法与传统的 COM 组件进行交互。其优点是可以在保留现有 COM 组件投资的同时利用 .NET 的功能。但是在某些情况下,保留旧组件的性能开销使得将组件迁移到托管代码是值得的。每一情况都是不一样的,决定是否需要迁移组件的最好方法是对网站运行性能测量。建议研究一下如何将经常调用的任何 COM 组件迁移到托管代码。

    许多情况下不可能将旧式组件迁移到托管代码,特别是在最初迁移 Web 应用程序时。在这种情况下,最大的性能障碍之一是将数据从非托管环境封送到托管环境。因此,在交互操作中,请在任何一端执行尽可能多的任务,然后进行单个调用而不是一系列小调用。例如,公共语言运行库中的所有字符串都是 Unicode 的,所以应在调用托管代码之前将组件中的所有字符串转换成 Unicode 格式。

    一旦处理完任何 COM 对象或本机资源就释放它们。这样,其他请求就能够使用它们,并且最大限度地减少了因稍后请求垃圾回收器释放它们所引起的性能问题。

  • 避免单线程单元 (STA) COM 组件 默认情况下,ASP.NET 不允许 STA COM 组件在页内运行。若要运行它们,必须在 .aspx 文件内将 ASPCompat=true 属性包含在 @ Page 指令中。这样就将页执行用的线程池切换到 STA 线程池,而且使 HttpContext 和其他内置对象可用于 COM 对象。避免使用 STA COM 组件是一种性能优化,因为它避免了将多线程单元 (MTA) 封送到 STA 线程的任何调用。

    如果必须使用 STA COM 组件,则应避免在执行期间进行大量调用,并尝试在每次调用期间发送尽可能多的信息。另外,避免在构造页面期间创建 STA COM 组件。例如在下面的代码中,在页面构造时将实例化由某个线程创建的 SampleSTAComponent,而该线程并不是运行页面的 STA 线程。这可能对性能有不利影响,因为要构造页面就需要在 MTA 和 STA 线程之间进行封送处理。

     “复制”图像复制代码
    <%@ Page Language="VB" ASPCompat="true" %>
    <script runat=server>
    Dim myComp as new SampleSTAComponent()
    Public Sub Page_Load()
        myComp.Name = "Sample"
    End Sub
    </script>
    <html>
    <%
        Response.Write(Server.HtmlEncode(myComp.SayHello))
    %>
    </html>

    首选机制是推迟对象的创建,直到在 STA 线程下执行上述代码,如下面的示例所示:

     “复制”图像复制代码
    <%@ Page Language="VB" ASPCompat="true" %>
    <script runat=server>
    Dim myComp
    Public Sub Page_Load()
        myComp = new SampleSTAComponent()
        myComp.Name = "Sample"
    End Sub
    </script>
    <html>
    <%
        Response.Write(Server.HtmlEncode(myComp.SayHello))
    %>
    </html>

    推荐的做法是仅在需要时或者在 Page_Load 方法中构造 COM 组件和外部资源。

    永远不要将 STA COM 组件存储在可以由构造它们的线程以外的其他线程访问的共享资源(如缓存或会话状态)里。即使 STA 线程调用 STA COM 组件,也只有构造此 STA COM 组件的线程能够为该调用服务,而这要求封送处理对创建者线程的调用。此封送处理可能产生重大的性能损失和可伸缩性问题。在这种情况下,请考虑使 COM 组件成为 MTA COM 组件或在托管代码中重写该组件。

请参见

概念
在 ASP.NET 中优化性能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值