http://www.360doc.com/content/14/0705/18/7662927_392224856.shtml

 

Asp.NET有许多秘密,当你了解了这些秘密后,可以使得你的ASP.NET应用程序达到极大的性能提升。举例来说,在使用Membership和profile进行Authentication和authorization时,可以通过简单的修改Membership和profile以提高Authentication和authorization的性能;ASP.NET Http 管道通过调整以避免执行不必要的HttpModules;不仅如此,浏览器端的页面缓存可以为重复浏览节省大量的下载时间;按需UI加载可以使网站更快、更平滑;最后,t适当的应用CDN(Cotent Delivery Networks)和应用Http Cache Header可以使网站更加快速。下面就让我们来分别讨论这些技巧,以提高我们ASP.NET网站的性能。

1 ASP.NET 管道最优化配置

用户每次请求网站时,都会有许多ASP.NET默认HttpModules去中断请求并进行一些处理,例如SessisonStateModule会中断每次的请求,解析session cookie信息并加载的适当的Session给HttpContent.但是这些默认的HttpModules并不都是必须的,例如如果你没有应用Forms Authentication来进行用户验证,那就不需要FormsAuthentication Module。

默认的Modules是在machine.config文件(该文件的位置为:$WINDOWS$\Microsoft.NET\Framework\$VERSION$\CONFIG directory))定义的,其定义如下:.

<httpModules>
<add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" />
<add name="WindowsAuthentication"
type="System.Web.Security.WindowsAuthenticationModule" />
<add name="FormsAuthentication"
type="System.Web.Security.FormsAuthenticationModule" />
<add name="PassportAuthentication"
type="System.Web.Security.PassportAuthenticationModule" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />
<add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule,
System.Web.Mobile, Version=1.0.5000.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</httpModules>

你要以通过在web.config中添加<remove>节点来移除不必要的httpModules,比如如果一个网站使用的是基于数据库的forms authentication验证并且没有使用任何Session则可以在web.config中添加如下节点:

<httpModules>
<!-- Remove unnecessary Http Modules for faster pipeline -->
<remove name="Session" />
<remove name="WindowsAuthentication" />
<remove name="PassportAuthentication" />
<remove name="AnonymousIdentification" />
<remove name="UrlAuthorization" />
<remove name="FileAuthorization" />
</httpModules>

2 ASP.NET进程最优化配置

ASP.NET进程模块配置了许多进程级别的属性,比如Asp.NET可以使用多少线程;超时多长时间后阻塞一个线程;在IO线程完成工作时,应该由多少个请求保持等待。默认的配置有许多限制,但是现在硬件变得越来越便宜,双核处理和GB的内存变成了标准配置,所以我们要以调整默认配置,让Asp.net进程使用更多的系统资源。

默认情况下,mechine.config文件中是这样配置asp.net进程的。

<system.web>

<processModel autoConfig="true" /> 

我们可以调整默认配置,为每个属性指定不同的值,以定制asp.net线程的工作模型,例如:

<processModel 

enable="true" 

timeout="Infinite" 

idleTimeout="Infinite" 

shutdownTimeout="00:00:05" 

requestLimit="Infinite" 

requestQueueLimit="5000" 

restartQueueLimit="10" 

memoryLimit="60" 

webGarden="false" 

cpuMask="0xffffffff" 

userName="machine" 

password="AutoGenerate" 

logLevel="Errors" 

clientConnectedCheck="00:00:05" 

comAuthenticationLevel="Connect" 

comImpersonationLevel="Impersonate" 

responseDeadlockInterval="00:03:00" 

responseRestartDeadlockInterval="00:03:00" 

autoConfig="false" 

maxWorkerThreads="100" 

maxIoThreads="100" 

minWorkerThreads="40" 

minIoThreads="30" 

serverErrorMessageFile="" 

pingFrequency="Infinite" 

pingTimeout="Infinite" 

asyncOption="20" 

maxAppDomains="2000" 

/> 

上面的属性基本上都是使用的默认值,除了下面的几个:

  • maxWorkerThreads :maxWorkerThreads的默认值是20/进程。在一个双核处理器的服务器中,会有40个线程分配给asp.net,这意味着双核服务器的asp.net在同一时间只能并行处理40个请求,为了分配给asp.net更多的线程,我把maxWorkerThreads的值改为100。特别需要注意的是,如果asp.net用完了线程,这时如果有新的请求进来,asp.net会将新来的请求放到等待队列,直到有线程释放为止,所以如果你的应用调用了许多web service或是有许多i/o操作,并且这些操作不会占用太多的cpu资源的话,你完全可以增大maxWorkerThreads的值。
  • maxIOThreads :maxIOThreads的默认值也是20/process,在一个双核处理器上,同样也有40个线程分配给asp.net来进行I/O操作,这也意味着在一个双核处理器上,同一时间asp.net只能并行处理40个I/O请求。这里我们说的I/O请求可以是文件读写、数据库操作、web service调用等。所以如果你的应用程序服务器有足够的资源来并行处理这些操作,你完全可以将maxIOThreads的值设的大一些,比如100.
  • minWorkerThreads :minWorkerThreads的默认值为1,它指出了分配给asp.net的最少辅助线程数。
  • minIOThreads : minWorkerThreads的默认值为1,它指出了分配给asp.net的最少I/O辅助线程数。
  • memoryLimit:以百分比的形式指定在 ASP.NET 启动新进程和重新分配现有请求前,辅助进程可以使用的最大内存大小。memoryLimit的默认值是60,如果你的服务器上只有你自己的应用程序,并且没有别的消耗内存的服务,那么你完全可以将memoryLimit设的大一些,比如80。

除了processModel之外,还有另外一个重要的节点要以配置,就是你可以在System.Net节点配置对一个IP所允许的最大并发请求数:

<system.net> 

<connectionManagement> 

<add address="*" maxconnection="100" /> 

</connectionManagement> 

</system.net> 

maxconnection的默认值是2,这意味着你不能在你的应用程序里同时对一个IP进行多于2个的请求。所以如果你的应用对一个特定的服务器进行了许多调用,你完全可以将maxconnection的值设的大一点,例如我在这里设为100。

3 在应用程序上线前必须做的事情

如果你的应用程序中应用了Membership Provider,那么在应用程序上线前,你不得不对web.config做一些调整:

    • 在Profile Provider中添加applicationname属性,如果你没有指定applicationname的值,那么profile Provider会将其值设为一个GUID,这意味着在你的开发机器上applicationname是一个GUID,在产品服务器上application是另一个GUID,所以你就没有重用开发机器上数据库里关于membership的数据。所以请按下面的格式指定applicationname的值:

          <profile enabled="true"> 
      <providers>
      <clear />
      <add name="..." type="System.Web.Profile.SqlProfileProvider"
      connectionStringName="..." applicationName="YourApplicationName"
      description="..." />
      </providers>
    • 每当一次请求完全,profile provider都会自动保存profile,这样我们的应用程序就因为大量的非必须的update操作降低了性能,所以关闭profile的自动保存并且在需要时,显示的通过Profile.Save()来保存。

      <profile enabled="true" automaticSaveEnabled="false" >
    • Role Manager每次都需要查询数据库来确定一个用户的角色,这同样也是一个很大的性能损失,我们可以通过将用户的角色缓存在cookie中来解决这个问题,但是请注意cookie的最大容量是2KB,所以如果我们有许多用户并且每个用户都有特别多的角色,就有可能超出cookie的容量,当然这种情况毕竟是少数,所以通常我们可以通过下面的设置将用户角色信息缓存在cookie中,以减少数据库访问次数。

      <roleManager enabled="true" cacheRolesInCookie="true" >

4  在客户端缓存Ajax请求

浏览器可以缓存图片、js文件、css文件,同样浏览器也可以缓存XML Http调用(当然这需要XML Http以get方式发送调用),这种缓存基于URL,当我们发送一个请求时,如果和以前请求的URL相同,那么浏览器就会从缓存中响应,而不是从重新请求服务器,这可以节省一些时间。通常来说,浏览器会缓存所有的Http get请求的结果,所以如果我们让XML Http以get方式发送请求,并且服务器返回特定的header告诉浏览器缓存结果,那么在以后的请求中,我们就可以直接从缓存中得到响应,从而节约了大量的时间。

在PageFlakes网站中,作者缓存了用户状态,所以如果用户重新登录网站,用户将会从浏览器缓存中得到一个缓存的页面而不是重新请求服务器,所以第二次访问是快很多,另外作者还缓存了许多用户的操作结果,所以当用户重新做相同的动作时,被缓存的结果会迅速的出现,这就使用户得到了更好的体验。

所以如果以http get方式调用Ajax请求时,我们应该返回特定的http header以告诉浏览器缓存请求的结果。下面是两种不同的方式,我们可以采取其中之一:

HTTP/1.1 200 OK 
Expires: Fri, 1 Jan 2030 
Cache-Control: public

上面的header告诉浏览器将请求结果缓存到2030年,所以如果我们在2030年之前发出同样的xml http请求,浏览器都会直接从缓存中读取结果,而不用重新请求服务器。另外还有一种更高级的header用来控件请求结果的缓存,下面的header指示浏览器也将请求结果缓存60分钟,并在60分钟后重新请求结果,

HTTP/1.1 200 OK 
Cache-Control: private, must-revalidate, proxy-revalidate, max-age=60

让我们尝试在Asp.NET web service响应中加入上述的header:

[WebMethod][ScriptMethod(UseHttpGet=true)]
public string CachedGet()
{
TimeSpan cacheDuration = TimeSpan.FromMinutes(1);
Context.Response.Cache.SetCacheability(HttpCacheability.Public);
Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
Context.Response.Cache.SetMaxAge(cacheDuration);
Context.Response.Cache.AppendCacheExtension(
"must-revalidate, proxy-revalidate"); return DateTime.Now.ToString();
}

上面的代码将会产生如下的response headwers :

从上图我们可以看到,Expires属性被正确的设置了,但是cache-control属性却没有被正确设置,其max-age的值是0,而不是60,这样浏览器就不会做任何缓存,所以当我们重新请求时,还是会请求服务器,而不是从缓存中返回结果。

这是Asp.net 2.0的一个bug,你无法改变max-age的值,这是因为在处理一个web services请求之前,asp.net ajax framework截取了请求并且错误地将max-age设置为0,这就意味着浏览器不会缓存ajax响应。

但是通过反编译HttpCachePolicy的代码,我们发现了如下代码段:

不知怎么地,只有在"if (!this._isMaxAgeSet || (delta < this._maxAge))" 时,才会设置_maxAge的值,这是不正确的,因为这阻止了将_maxAge的值设为一个大于当前值的值。所以我们需要通过反射来绕过SetMaxAge方法去设置_maxAge的值:

[WebMethod][ScriptMethod(UseHttpGet=true)]
public string CachedGet2()
{
TimeSpan cacheDuration = TimeSpan.FromMinutes(1); FieldInfo maxAge = Context.Response.Cache.GetType().GetField("_maxAge",
BindingFlags.Instance|BindingFlags.NonPublic);
maxAge.SetValue(Context.Response.Cache, cacheDuration); Context.Response.Cache.SetCacheability(HttpCacheability.Public);
Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
Context.Response.Cache.AppendCacheExtension(
"must-revalidate, proxy-revalidate"); return DateTime.Now.ToString();
}

上面的代码返回如下的header:

现在我们可以看到 max-age的值是60,并且浏览器会缓存结果60分钟,如果你在60分钟内进行相同的调用,浏览器将会从缓存中响应。一分钟后,缓存过期,浏览器会自动发送一个请求,那个请求的代码就像下面一样:

function testCache()
{
TestService.CachedGet(function(result)
{
debug.trace(result);
});
}

请注意,这里还有一个问题,因为asp.net ajax的默认信任级别是中等的,

<system.web>
<trust level="Medium"/>

而我们的CachedGet2方法却用到了反射,所以仅有中等信任是不够的,我们需要按如下的方式修改web.config文件:

<system.web> 
<trust level="Full"/>

5 更好的应用浏览器缓存

使用一致的URL

浏览器缓存的基础是URL,当一个URL改变时,浏览器就会从服务器重新请求页面。我们可以通过不同的查询参数来改变URL,例如我们在缓存中缓存了default.aspx页面,如果我们再请求default.aspx/?1页面,这时虽然是相同的操作,但浏览器仍会重新请求服务器,另外如果在Header中做了设置,新的请求结果也会被缓存。因此我们要确保使用一致的URL。一个常见的错误是在是URL中省略www,例如www.cnblogs.com/zhangronghuacnblogs.com/zhangronghua会被分别缓存。

将静态内容的缓存周期设的长些

静态文件可以设置一个长的缓存周期,比如一个月。如果你认为你应该缓存两天,这样当你改变了文件后,用户就可以很快的得到新的文件,这就你错了,当你更新了一个被expires缓存的文件后,新用户会立即得到更改后的文件,而老用户只有在缓存到期后才能得到更改后的文件。所以只要你应用了Expires去缓存静态文件,就应该将过期周期设的尽可能地大。

例如如果你将一个静态文件的缓存周期设为三天,一个用户A在今天访问页面并将其缓存三天,另一个用户B在明天访问页面并同样缓存页面。所以如果你在后天改变了文件,那么用户A将会在第四天看到新文件,用户B将会在第五天看到新文件,这就会导致不同的用户看到不同的文件,这不是我们想要的结果,所以如果我们更改了文件并将想让用户立即看到更改后的文件,我们应该通过不同的URL来访问文件。

使用缓存友好地目录结构

尽量将需要缓存的文件放在一个目录中,例如将所有的image放在images目录中,而不是分别放在不同的目录中,这样我们就要以在整个网站中使用一致的URL来请求图片。

重用公共图片

有时我们为了少写一些路径,会将一个公共图片放到许多不同的目录中,这样我们就会在文件中只使用图片名来引用图片,而不是基于相同路径,这样做虽说方便了我们的书写,却不是缓存友好的,公共文件的每一个copy都会在缓存中缓存一份。所以我们需要做的就是将公共文件放到一个统一的目录中,在页面中使用相对路径来引用它。

当你修改静态文件后,记得修改文件名

当你修改了一个静态文件后,不要以为修改好了文件就万事大吉了,因为静态文件会在客户端缓存,所以当你修改了静态文件后,一定要记得为其重命名,因为这样可 以确保用户可以立即看到你修改后的文件,而不是缓存了浏览器缓存中的修改前的文件。

使用版本号去访问静态文件

如果你不想每次修改静态文件名后都为其重命名,那么你也可以使用带版本号的URL去访问静态文件,例如GIF文件可以通过带哑查询字符中的URL访问,你可以通过/images/1.gif?v=1去访问1.gif文件,当1.gif文件改变后,你要以通过/images/1.gif?v=2来访问1.gif文件,这样也可以保证用户会立即看到修改后的文件。

将缓存文件放在单独的域中

将缓存文件放在一个单独的域中是一个好主意。首先浏览器也以并发的请求静态文件。其次你不必发送cookies给静态文件,当你将静态文件和应用程序放在同一个域中时,浏览器会在你请求静态文件时,将应用程序产生的cookies也一并发送,而这些cookies对静态文件不是必须的。所以如果我们将静态文件单独放在一个域中,就要以将避免发送这些cookies。例如我们可以将静态文件放在http://www.zhangronghua.com/中,而将我们的应用程序放在真正的http://www.application.com/中,http://www.zhangronghua.com/不必是一个真正的网站,它可以只是一个别名并且和http://www.application.com/指向共同的目录。

SSL 是非缓存的,所以请适当使用

SSL是非缓存的,所以不要通过SSL请求静态文件,另外,我们仅应该在登录页面和支付页面这样的情境下使用SSL,除此之外不应该在程序中使用SSL。SSL需要加密请求和响应,所以增加了服务器的负担,同时加密后的响应内容也更长,会占用更多的带宽。

HTTP POST请求不会被缓存

浏览器只会缓存Http Get请求,不会缓存Http Post请求,所以如果你想要缓存一个文件时,请确保以http get方式请求文件。

显示指明Content-Length 属性

当你通过web service或是http hadler请求一个动态内容时,请确保设置了response header的content-length属性。当浏览器从响应的header中读取到content-lengtg属性时,它会对响应做一些优化以加快下载速度。当指定了content-length后,浏览器会使用持续的连接请求资源,这就避免了浏览器针对每次请求都新建连接。

如何在IIS中缓存静态内容

在IIS管理器中,右击应用程序名,选择“属性”,我们可以看到下图:

选择“启用内容过期”就可以缓存静态内容了。具体的设置很简单,这里就不说了。

6 总结

以上列举了Asp.NET应用程序的部分优化方法,主要包括Asp.net管道最优化配置、Asp.net线程最优化配置和静态文件、Ajax调用缓存。希望对大家所帮助!

提高ASP.NET网站性能的方法的更多相关文章

  1. 提高ASP.NET首页性能的方法

    1.js压缩文件,css压缩文件,引用的越少越好. 2.用 HTTP Module 控制页面的生命周期. 3.自定义生成动态页面的静态内容 . 4.页面用GZIP压缩. 5.OutputCache 编 ...

  2. ASP.NET网站性能优化

    如果你是一个做过ASP网站,又做过ASP.NET网站的程序员,你可能会发现,如果按正常的思路开发ASP.NET网站,ASP.NET网站的速度会比ASP网站慢很多,为什么强大的网站语言会比弱得慢的,原因 ...

  3. 26种提高ASP.NET网站访问性能的优化方法 .

    1. 数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源. ASP.NET中提供了连接池 ...

  4. 不修改代码就能优化ASP.NET网站性能的一些方法

    阅读目录 开始 配置OutputCache 启用内容过期 解决资源文件升级问题 启用压缩 删除无用的HttpModule 其它优化选项 本文将介绍一些方法用于优化ASP.NET网站性能,这些方法都是不 ...

  5. 不修改代码优化 ASP.NET 网站性能的一些方法

    本文将介绍一些方法用于优化ASP.NET网站性能,这些方法都是不需要修改程序代码的.它们主要分为二个方面:1. 利用ASP.NET自身的扩展性进行优化.2. 优化IIS设置. 配置OutputCach ...

  6. 不修改代码就能优化ASP.NET网站性能的一些方法 [转]

    不修改代码就能优化ASP.NET网站性能的一些方法 阅读目录 开始 配置OutputCache 启用内容过期 解决资源文件升级问题 启用压缩 删除无用的HttpModule 其它优化选项 本文将介绍一 ...

  7. (摘录)26个ASP.NET常用性能优化方法

    数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源. ASP.NET中提供了连接池(Co ...

  8. 26个ASP.NET常用性能优化方法

    数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源. ASP.NET中提供了连接池(Co ...

  9. 如何真正提高ASP.NET网站的性能

    摘要:前言 怎么才能让asp.net网站飞得更快,有更好的性能?这是很多开发者常常思考的一个问题.我有时候会做大量的测试,或请求别人帮忙采集一些数据,希望能够验证网上一些专家的建议或证明 前言 怎么才 ...

随机推荐

  1. Maven + Apache Felix + CXF + DOSGi series

    This is a blog series on how to combine Maven + Apache Felix + CXF + DOSGi. The information presente ...

  2. JavaScript 对象与数组参考大全

    http://www.cnblogs.com/meil/archive/2006/06/28/437527.html本文列举了各种JavaScript对象与数组,同时包括对上述每一对象或数组所完成工作 ...

  3. AFLW如何获取你想要的21点人脸关键点数据

    目前人脸检测和人脸的关键点的数据库根据关键点个数:5,20,21,29,68等.https://blog.csdn.net/XZZPPP/article/details/74939823该网页详细列出 ...

  4. python --curl重定向到文件范例

      import sys import os import subprocess import time start = time.time() old=sys.stdout f=open('test ...

  5. 文件流(fstream, ifstream, ofstream)的打开关闭、流状态

    一.文件流 ofstream,由ostream派生而来,用于写文件 ifstream,由istream派生而来, 用于读文件 fstream,由iostream派生而来,用于读写文件 二.打开文件 说 ...

  6. 学习XML(添加一个子节点) 摘录

    这里介绍添加XML节点的方法. 首先定义XML文件:(bookstore.xml) <?xml version="1.0" encoding="utf-8" ...

  7. Mysql 数据库数值类型详解

    MySQL 支持所有标准SQL 中的数值类型,其中包括严格数值类型(INTEGER.SMALLINT.DECIMAL 和NUMERIC),以及近似数值数据类型(FLOAT.REAL 和DOUBLE P ...

  8. Java callback

    Java中的回调(callback)是很重要的一个概念,spring整合hibernate大量使用了这种技术. 究竟怎样才是回调呢? 这是网上最多见到的说明:     1.class   A,clas ...

  9. Android 开发之Android 应用程序如何调用支付宝接口

    1.到支付宝官网,下载支付宝集成开发包 由于android设备一般用的都是无线支付,所以我们申请的就是支付宝无线快捷支付接口.下面是申请的地址以及下载接口开发包的网址:https://b.alipay ...

  10. 等边三角形---dfs

    蒜头君手上有一些小木棍,它们长短不一,蒜头君想用这些木棍拼出一个等边三角形,并且每根木棍都要用到. 例如,蒜头君手上有长度为 11,22,33,33 的4根木棍,他可以让长度为11,22 的木棍组成一 ...