ASP.NET站点性能提升-压缩
压缩协商
服务器怎么知道浏览器能够接收压缩内容?浏览器怎么知道接收的内容是压缩过的?
当支持压缩的浏览器向服务器发送请求时,会包含一个Accept-Encoding请求头,告诉服务器它支持的压缩算法。例如:
Accept-Encoding: gzip,deflate
如果服务器响应使用了压缩,会在未压缩的文件头中包含一个响应头Content-Encoding,说明文件是怎么压缩的:
Content-Encoding: gzip
然而,不仅仅浏览器和服务器发送和接收请求和响应,代理也会。并且,代理也可以缓存响应,然后从它的缓存中响应后来的请求。当代理缓存了一个压缩后的文件,我们怎么确定代理不会发送这个压缩后的文件给不能处理压缩文件的浏览器。
IIS6和II7采取的方法是告诉代理只有当请求与原请求有相同的Accept-Encoding请求头时,才从缓存中响应请求。当启用压缩时,IIS6和IIS7在响应中包含Vary头:
Vary: Accept-Encoding
IIS6也允许通过元数据中的属性重载压缩文件Cache-Control和Expires头。这允许禁用压缩文件的代理缓存。IIS元数据在在IIS6中配置压缩节的更新元数据子节,重载Cache-Control和Expires头的元数据属性可以在以下位置找到:
- HcCacheControlHeader http://msdn.microsoft.com/en-us/library/ms525179(VS.90).aspx
在IIS7中配置压缩
安装动态内容压缩模块
如果需要对动态文件使用压缩,首先安装动态内容压缩模块。Vista/Windows 7或Windows Server 2008的安装步骤有些不同:
- 点击Start | Administrative Tools | Server Manager。
- 展开Roles,点击Web Server(IIS)。
- 滚动到Role Services,点击Add Role Services,打开Add Role Services向导。
- 在Select Role Services页面,滚动到Performance,选择Dynamic Content Compression,选择下一步。
在Vista或Windows 7上:
- 点击Start | Control Panel | Programs | Turn Windows features on or off。Windows Features对话框会打开。
- 展开Internet Information Service,展开World Wide Web Services,再展开Performance Features。选择Http Compression Dynamic。
启用压缩
- 打开Internet Information Services (IIS) Manager。
- 选择机器,双击右侧的Compression图标。
- 压缩窗口打开。窗口显示以下项目:
- Enable dynamic content compression: 除非服务器已经使用了很多CPU,启动动态内容压缩。
- Enable static content compression: 压缩的静态内容会被压缩。所以只在初始压缩时,会占用CPU周期。
- Only compress files larger than (in bytes): 压缩小文件可以会使得它更大。
- Cache directory: 静态文件的存储位置。可以更换位置。确保驱动器是本地驱动器或NTFS分区,并且没有被压缩或共享。
- Per application pool disk space limit (in MB): 如果有很多应用程序池,并且磁盘空间有限,可以调整。如果有100个应用程序池,这个选项值为100MB,缓存静态文件会使用100 * 100 MB = 10GB。
针对站点、文件夹或文件设置压缩
- 打开IIS管理器,在左侧点击需要修改压缩状态的站点、文件夹或文件。
- 切换中间的空格到Features View,双击Compression图标。
- 打开的窗口中可以启动或禁用动态或静态文件的压缩。
压缩等级
压缩等级超高,压缩比率越大,CPU占用越大。
静态文件和动态文件的压缩等级可以分别设置。对于静态文件,使用9,最高等级。对于动态文件,压缩等级4更好一点,可以参考:
IIS 7 Compression. Good? Bad? How much? http://weblogs.asp.net/owscott/archive/2009/02/22/iis-7-compression-good-bad-how-much.aspx.
但是不同的网站最优压缩等级是不一样的,这取决于空闲的CPU能力、页面文件压缩率、带宽成本。进行实验选择最优的压缩等级。
设置压缩等级:
- 从命令行执行:
C:\Windows\System32\Inetsrv\Appcmd.exe set config -section:httpCompression -[name='gzip'].staticCompressionLevel:9 -[name='gzip'].dynamicCompressionLevel:4
- 重启IIS服务器。
根据CPU利用率禁用压缩
为了确保压缩没有使CPU超载,IIS7每30秒计算平均CPU利用率。当CPU利用率超过一个限制时,它会自动关闭压缩。当CPU利用率低于限制时, 它会重新启用压缩。
限制的默认值是:
关闭压缩 | 重启压缩 | |
动态文件 | 90% | 50% |
静态文件 | 100% | 50% |
注意这意味着如果服务器上的CPU一直在50%以上,但偶然高于90%,动态文件压缩会被关闭,但再也不会重新开启了。
可以通过修改applicationHost.config文件修改这些限制,通常它在C:\Windows\System32\inetsrv\config文件夹下。
- 找到<httpCompression>节。
- 修改httpdynamicCompressionEnableCpuUsage属性:
<httpCompression dynamicCompressionEnableCpuUsage="70" .... >
- 重启IIS。
如果需要修改其它限制,修改属性:
关闭压缩 | 重启压缩 | |
动态文件 | dynamicCompressionDisableCpuUsage | dynamicCompressionEnableCpuUsage |
静态文件 | staticCompressionDisableCpuUsage | staticCompressionEnableCpuUsage |
如果希望禁止IIS根据CPU利用率关闭压缩,设置这些属性值为100。
与httpCompression一起使用的元素和属性:
- HTTP Compression <httpCompression>
http://www.iis.net/ConfigReference/system.webServer/httpCompression.
设置静态文件访问频率阈值
只有当静态文件被频繁请求时,IIS7才会压缩静态文件并将它放到缓存中。如果请求频率不高,IIS7不会压缩静态文件,这样可以节省CPU和缓存空间。
默认情况下,一个文件只有每10秒被请示2次或更多次时,才会被认为是频繁请求。这是在web.config的serverRuntime元素的两个属性决定的:
serverRuntime属性 | 描述 |
frequentHitThreshold | Number of times a URL must be requested within the time span specified in the frequentHitTimePeriod attribute to be considered frequently hit. Must be between 1 and 2147483647. Default is 2. |
frequentHitTimePeriod | Time interval in which a URL must be requested the number of times specified in the frequentHitThreshold attribute before it is considered to be frequently hit. Default is 10 seconds. |
例如,指定静态文件每隔15秒被请求7次,需要缓存,使用:
<configuration> ... <system.webServer> <serverRuntime frequentHitThreshold="7" frequentHitTimePeriod="00:00:15" /> </system.webServer> ... </configuration>
缓存压缩的动态文件
IIS7只缓存静态文件的压缩版本,而动态文件在每次请求时进行压缩。这意味着压缩动态文件比静态文件占用更多的CPU。
如果动态文件对每个访问者都不同时,这是有意义的。但是,如果动态页面对所有访问者都一样的,缓存它们的压缩版本也是有意义的。
在这种情况下可以使用ASP.NET OutputCache指令。这个方法的问题是,IIS默认在输出缓存中存储文件的未压缩版本。对于每个请求,IIS必须在发送到浏览器前压缩缓存的内容。这样的效率很低。
在输出缓存中存储压缩的文件
IIS缓存文件的压缩版本,而不是未压缩版本。这样就不用在每次请求时都压缩文件,减少了CPU的使用。
因为使用了ASP.NET的输出缓存,需要在页面中加入OutputCache指令:
<%@ OutputCache Duration="300" VaryByParam="none" %>然后,修改applicationHost.config文件,它通常在C:\Windows\System32\inetsrv\config文件夹中:
- 找到<urlCompression>节。
- 在urlCompression元素中加入 dynamicCompressionBeforeCache="true"属性。
- 重启IIS。
如果客户端不接受压缩后的内存
我们缓存了压缩后的内容,如果有一个访问者使用不支持压缩内容的浏览器访问了网站会发生什么?
当IIS收到请求不压缩内容的请求,会丢弃缓存中的压缩内容,重新生成内容,并缓存未压缩的内容。它会一直使用未压缩的内容,直到缓存过期,即使客户端能够接受压缩内容。
可以通过同时缓存压缩和未压缩版本解决这个问题。在OutputCache指令中加入VaryByContentEncoding:
<%@ OutputCache Duration="300" VaryByParam="none" VaryByContentEncoding="gzip;deflate" %>在OutputCache指令中使用VaryByContentEncoding的一个缺点是这会禁用这个文件的内核缓存。
在IIS6中配置压缩
略
提高页面的可压缩性
如果服务器使用了压缩,优化文本文件的可压缩性是很有意义的。压缩算法对重复内容的效果最好:
- 始终以同一顺序指定HTML属性。其中一个方法是使用高级web控件和自定义服务器控件生成HTML,不要使用低级HTML服务器控件。这会稍微提高CPU使用率,但会保证一致性,例如,使用
<asp:Hyperlink runat="server"......>
代替
<a runat="server" .... > - 类似地,在CSS选择器中,以字母顺序书写属性。
- 使用一致的大小写。对HMTL标签和属性使用小写。
- 使用一致的括号:不要混用”….”和’….’。
更多资源
- 10 Tips for Writing High-Performance Web Applications
http://msdn.microsoft.com/en-us/magazine/cc163854.aspx - Confguring HTTP Compression in IIS 7
http://technet.microsoft.com/en-us/library/cc771003(WS.10).aspx - IIS 6.0 Technical Reference
http://technet.microsoft.com/en-us/library/cc775635(WS.10).aspx - IIS Compression in IIS6.0
http://weblogs.asp.net/owscott/archive/2004/01/12/57916.aspx - Everything you ever wanted to know about compression, but were afraid to ask
http://geekswithblogs.net/JamesFleming/archive/2010/02/04/everything-you-ever-wanted-to-know-about-compression-but-were.aspx - Measuring the Performance Effects of Dynamic Compression in IIS 7.0
http://www.webperformanceinc.com/library/reports/iis7_compression/ - Let's make the web faster
http://code.google.com/speed/articles/use-compression.html - Page Speed tool
http://code.google.com/speed/page-speed/download.html