文章系统图片系统下载系统个人求职企业招聘房产系统展会系统供求系统产品系统商城系统自定义系统后台一览
解决方案
建站知识
提高ASP.NET网站性能的方法
来源:网络作者:网络

 

 

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

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

  • 在Profile Provider中添加applicationname属性,如果你没有指定applicationname的值,那么profile Provider会将其值设为一个GUID,这意味着在你的开发机器上applicationname是一个GUID,在产品服务器上application是另一个GUID,所以你就没有重用开发机器上数据库里关于membership的数据。所以请按下面的格式指定applicationname的值:
    <profileenabled="true">ITPUB个人空间\&Y/v(q|4G
    <providers>
    tNI.W{G vA ~J0<clear/>
    .TU_yE0<addname="..."type="System.Web.Profile.SqlProfileProvider"
    S#W^S7f$n]G0connectionStringName="..."applicationName="YourApplicationName"
    2uS#jWIHy#_EC0description="..."/>
    Qo SB|AXK0</providers>
    /fE*I2hXOU$M0
    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }每当一次请求完全,profile provider都会自动保存profile,这样我们的应用程序就因为大量的非必须的update操作降低了性能,所以关闭profile的自动保存并且在需要时,显示的通过Profile.Save()来保存。
    <profileenabled="true"automaticSaveEnabled="false">
    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }Role Manager每次都需要查询数据库来确定一个用户的角色,这同样也是一个很大的性能损失,我们可以通过将用户的角色缓存在cookie中来解决这个问题,但是请注意cookie的最大容量是2KB,所以如果我们有许多用户并且每个用户都有特别多的角色,就有可能超出cookie的容量,当然这种情况毕竟是少数,所以通常我们可以通过下面的设置将用户角色信息缓存在cookie中,以减少数据库访问次数。
    <roleManagerenabled="true"cacheRolesInCookie="true">
    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

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)]ITPUB个人空间^s1F4^x|%E
publicstringCachedGet()ITPUB个人空间I-c n,T&u7F%u
{ITPUB个人空间.nM,__~,HtI"z'y
TimeSpan cacheDuration = TimeSpan.FromMinutes(1);ITPUB个人空间c)O;q XfTE6C
Context.Response.Cache.SetCacheability(HttpCacheability.Public);
6it(S \2EbZ)JH0Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));ITPUB个人空间c(i4E)]c$H4F!X
Context.Response.Cache.SetMaxAge(cacheDuration);ITPUB个人空间M2F7p` uMfJ
Context.Response.Cache.AppendCacheExtension(ITPUB个人空间)ZX8r1GVq
"must-revalidate, proxy-revalidate");
1G\Y![t7tvAh qn0ITPUB个人空间mU*X:b2f
returnDateTime.Now.ToString();ITPUB个人空间(SgfVk%WO'g{
}ITPUB个人空间cY%b"w6m9y;qa'x

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }上面的代码将会产生如下的response headwers :

 

clip_image007 

从上图我们可以看到,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的代码,我们发现了如下代码段:

clip_image010

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

[WebMethod][ScriptMethod(UseHttpGet=true)]
+i7Y+~^ F6u0publicstringCachedGet2()
1S"S@pz(v0{
M[A?3Tk `*l0TimeSpan cacheDuration = TimeSpan.FromMinutes(1);ITPUB个人空间v,\,P1o;Zt.Eg
ITPUB个人空间me-[;Qv#B
FieldInfo maxAge = Context.Response.Cache.GetType().GetField("_maxAge",
`/wB2SIH2E.P%O ~0BindingFlags.Instance|BindingFlags.NonPublic);ITPUB个人空间5q`ln\Q
maxAge.SetValue(Context.Response.Cache, cacheDuration);
5o0FhEQ.T0
Q!}6P s%y0Context.Response.Cache.SetCacheability(HttpCacheability.Public);ITPUB个人空间%t1jbGA#jdD B-H
Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
A"X2?5a4~/\1N7S0Context.Response.Cache.AppendCacheExtension(ITPUB个人空间^)VEW\w k_
"must-revalidate, proxy-revalidate");ITPUB个人空间"Xx@u%z[;S
ITPUB个人空间 _,o#D3cdm6Jy
returnDateTime.Now.ToString();
KON#}5^_WA0}ITPUB个人空间B#Lau$J7~Q u

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }上面的代码返回如下的header:

 

clip_image012

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

functiontestCache()ITPUB个人空间s2Ju4Kw)J
{ITPUB个人空间C%cun%Zf7A;qd
TestService.CachedGet(function(result)
JK]*b1P!f0\!b0{
+NY/F\{Ph:c0debug.trace(result);
(LMi0A8?2|t;U o)BJ0});ITPUB个人空间 JCeWOk8}1b"C9{7]p
}
],YV$M4@ y+_(eQt0

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }请注意,这里还有一个问题,因为asp.net ajax的默认信任级别是中等的,

 

<system.web>
5T*KhZ8d W0<trustlevel="Medium"/>ITPUB个人空间 h W1N+D4}PlY

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }而我们的CachedGet2方法却用到了反射,所以仅有中等信任是不够的,我们需要按如下的方式修改web.config文件:

 

<system.web>ITPUB个人空间7Cx]3O'Da$oA2R2s
<trustlevel="Full"/>ITPUB个人空间4Tn5IrL"?,S

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }5 更好的应用浏览器缓存

 

使用一致的URL

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