HttpCombiner.ashx处理

httpcombiner.ashx是一个http处理程序,通过它能够合并多个css,javascript或者url成为一个响应让页面载进加速。同时它可以合并,压缩并缓存响应,这样就使得我们的应用程序更快的加载和具备更好的扩展性。

先容

用一个大的javascript或者css文件替换多个小体积的javascript和css文件这是一个很好的实践,可以获得更好的可维护性,但是在网站性能方面会产生一定的影响(这里指的是随着文件体积的增大,随之消耗服务器的内存也会增加)。尽管你应该把javascript代码单独写成小支的文件,css文件拆分成小块,但是当浏览器请求这些文件时,会产生同等数目的http请求。每个http请求都会产生一次从你的浏览器到服务器端网络往返过程,并且导致推迟到达服务器端和返回浏览器真个时间,我们称之为延迟。因此,假如你有4个javascript和3个css文件在页面中被加载,你浪费掉了7次因网络往返过程产生的时间。在美国,延迟均匀是70毫秒,这样你就浪费了7*70 = 490毫秒,大致延迟了半秒的时间。在美国之外的国家访问你的页面,均匀延迟大约是200毫秒,这意味着你的页面有1400毫秒的时间是在等待中度过。浏览器在你的css和javascript文件完全加载完成之前是不能很好的渲染你的页面的。因此越多的延迟让你的页面载进越慢。

延迟导致多大的影响

下图显示每个请求的延迟造成页面加载时明显的延误

你可以通过使用cdn加速来减少等待时间。阅读我前一篇文章关于使用cdn. 然而,一个更好的解决方案是使用一个httphandler来合并多个文件成一个文件一次性输出。因此,你只要将多个《script》或者《link》标签合并成为一个并将他们指向httphandler,指定哪些文件需要作为一次响应传输到浏览器段。这样就减少了请求次数以及消除因其造成的延迟this saves browser from *** many requests and eliminates the latency.

通过上图你可以看见通过合并多个javascripts和css文件为一所带来各方面的提升。

在一个电影的web页面中你会看到很多javascripts引用

 

<scripttype="text/javascript"src="http://www.msmvps.com/content/jscript/jquery.js"></script>
<美女图片r: #800000">scripttype ="text/javascript"src="http://www.msmvps.com/content/jscript/jdate.js"></script>
<script type="text/javascript"src="http://www.msmvps.com/content/jscript/jquery.core.js"></script>
<scripttype="text/javascript"src="http://www.msmvps.com/content/jscript/jquery.delegate.js"></script>
<scripttype="text/javascript"src="http://www.msmvps.com/content/jscript/jquery.validation.js"> </ script >

你可以用http handler通过scripts的设置来实现将多个单独的 《script》标签合并成一个:

 

<script type="text/javascript"  src="httpcombiner.ashx?s=jqueryscripts&t=text/javascript&v=1"></script>

http handler 通过配置文件中设置的名称读取所有文件合并成一次响应传输到客户端,通过gzip压缩响应节省了宽带使用。此外还会天生合适的缓存头来缓存响应的浏览器缓存,因此,浏览器不会再次向服务器发送请求。

在查询字符串中,‘s’指明配置文件中的设置名,‘t’为文件的内容类型,‘v’为版本号。一旦响应被缓存,假如你更改了配置中任何文件,你将不得不增加参数‘v’的值来让浏览器再次下载服务器端最新的响应:

 

<linktype="text/css"rel="stylesheet"href="httpcombiner.ashx?s=commoncss&t=text/css&v=1"></link>

在web.config中的设置如下:

 

<appsettings>
   <add key="jqueryscripts" value="~/content/jscript/jquery.js,
            ~/content/jscript/jdate.js,
            ~/content/jscript/jquery.core.js,
            ~/content/jscript/jquery.delegate.js,
            ~/content/jscript/jquery.validation.js"
/>
   <add key="commoncss" value="~/app_themes/default/theme.css,
            ~/css/common.css,
            ~/controls/grid/grid.css"
/>
</appsettings>

 

使用httpcombiner实现一个网站示例

我已经写好一个测试网站来演示如何使用httpcombiner.网站包含2个css和2个js文件。 default.aspx文件中《link》和《script》标签2个请求都是指向了httpcombiner.ashx文件 。

下面就是default.aspx的内容:

就如你所见,页面中 《link 》和《script》标签 都同时指向了 httpcombiner.ashx,并且所带的参数&lsq游戏问答uo;s’就是web.config文件中定义的2组设置 :

该处理程序如何工作:

1、首先通过传进的参数“s”获得设置名称

2、然后根据设置名称获得web.config中定义的文件名称(通过特定的分隔符分隔开)

3、读取每单个文件然后存储到缓冲区

4、通过gzip压缩缓冲区中的数据

5、发送压缩后缓冲区中的数据到浏览器端

6、已压缩后缓冲区的数据使用asp.net缓存模块缓存起来以便在频繁请求同一个设置的情况下直接访问缓存而不必从文件系统或者外部url读取文件

该处理程序带来的好处:

可以节约因网络延迟造成的时间。假如一次性设置的文件越多,节省的网络延迟性时间越多,同时得到的性能提升就越可观。

由于缓存了所有压缩后的响应数据,这样节省了反复执行从文件系统中读取并压缩的步骤,提升了应用程序的伸缩性。

 

如何让httphandler工作

首先处理程序会从querystring中获取setname,contenttype,version三个关键参数:

假如设置的文件已经被缓存起来,它将直接被写进到缓存当中往,否则它们会从memorystream中分别被加载。假如浏览器支持压缩输出的话,memorystream会使用gzipstream进行压缩

当合并所有文件之后并压缩,合并的二进制流被缓存起来便与频繁的访问可以直接从缓存中读取。

getfilebytes方法主要是根据文件路径或者http url读取文件并返回二进制。因此您可以使用你站点的虚拟路径或者使用外部站点javascript/css的url

 

writebytes 方法很巧妙,它会基于二进制流是否为压缩而天生一个合适的header,并设置浏览器缓存头让浏览器缓存服务器真个响应

目前发现部署到运行环境中会出现异常(远程主机封闭了连接。错误代码是 0x80072746。),将上面图片中的代码最后2行替换成

 

response.flush();
if (response.isclientconnected)
    response.outputstream.write(bytes, 0, bytes.length);
response.end();

如何使用该文件:

包含httpcombiner.ashx在你的项目中

在你的web.config的 <appsettings>定义需要设置的文件节点

更改你网站的 <link><script> 标签指向httpcombiner.ashx 如下面的格式:

httpcombiner.ashx?s=<appsettings里设置的节点名>&t=<文件类型>&v=<版本号>

结尾

本文是在优化实际项目中的总结,解决方案源自网上并加以翻译和整理而成,有不当之处或者建议请大家一起讨论。

posted @ 2012-05-29 17:42  岁月无情--老胡  阅读(459)  评论(0编辑  收藏  举报