构建高性能ASP.NET站点 开篇作者:小洋,燕洋天
出处:http://yanyangtian.cnblogs.com/ 本篇的议题如下: 网站优化需要考虑的方面 网站优化需要考虑的方面 在用ASP.NET开发网站的时候,性能是永远需要考虑和关注的问题,性能不仅仅只是程序代码执行时候的速度,而是涉及到方方面面的东西。 就拿ASP.NET的一个请求来讲,从浏览器向服务器的ASP.NET网站发送请求开始一直到最后整个页面呈现在我们面前,其中请求经过的每一个步骤,都是有不同的调优方式的,而且调用的方法也很多,不仅仅只是常见的:缓存,多线程,异步等。 本系列的文章决定从两个大的方面来讲述调优: 前台调优:主要包含如何尽量的减少http请求,从http请求开始,到如何加载js, css,如何压缩传输的数据等。 后台调优:分析ASP.NET请求的处理过程,并在每一步给出相应的调优方法,而且在代码组织,架构和数据库的操作上面给出调优的方法。 记得在刚刚开发网站的时候,一提到提高性能,最容易也是最快想到的就是缓存,而且在微软官方的Best Practice的一些文档中也是建议:层层缓存(在数据存储层,DAL,BLL,UI等都要缓存)。然后在网站中就”缓存遍地开花”,最后的确实不尽人意。 另外的一个常见的优化针对数据库的:如尽量减少子查询,使用join联接;在常常需要查询的字段上面建立索引。确实,这些是很通用,也不错的一些规则。 而且还有一个体会就是,在优化性能的时候,如果选择优化代码和数据库,往往优化数据库的一些操作带来的效果会更加的好,很可惜的是:在项目中(至少在我开发的一些项目中),数据库仅仅就只是一个数据的存储设备而已,仅此而已,没有发挥出数据库的强大作用。所以还是建议对数据库的内部查询和存储的机制要熟悉,毕竟很多时候开发人员也担任了DBA的工作(很多公司没有正式的DBA)。 而且在项目中我们设计数据库的时候,特别是表字段的时候,是需要有些考虑的,很多人建议表字段的长度不要太长,这也是大家常见的建议,但是为什么?其实,这就需要懂得一些数据库的内部存储机制了:在数据库(SQL SERVER )保存的时候,数据是以”页”为最小的单位的,每一页有8K的大小,如果你的一个表中的数据超过8K,那么这个表的数据就要分几个页面保存,这样在对数据进行查询的时候,就要跨页查询了,跨页是需要性能消耗的,如果数据都在一个页面上,那么速度肯定快些。 所以,要优化网站,就得知道性能消耗在哪里。 当优化的一个网站的时候,不是盲目的一概而论的,一般来说有两种情况: 1. 网站已经存在了,并且运行了,现在要优化。 2. 正在从头开发一个新的网站。 如果是第一种情况,那么首先要找出网站性能的瓶颈,从前台的请求的到后台的请求处理,一直到最后页面的呈现,都要一步步的审查。 如果是第二种情况,可能情况就稍微好一点,并且网站现在完全由我们控制,所有在开发和设计的过程中就可以采用很多的优化原则来优化。 优化不一定就是代码重写或者做些很大的改动,优化时一点点的累积的,就好比代码的重构一样,都是一个积累的效果。比如,是在页面一开始的时候载入js脚本,还是在整个页面的最后载入js脚本,有时候往往就只是简单的调整一下载入的文件,或者异步的载入脚本,或者通过CDN传输脚本等等方法,性能就提升了。性能的提升也不是没有代价的,有的代价很小,例如只是把脚本的载入放在页面最后,大的代价就是,例如买些服务器设备,如Content Delivery Network(CDN)来把静态的文件(js,css,image)传送到客户端。所以说,优化需要权衡策略。 不知道大家是否有过这样的体会:当看着自己开发出来的系统性能很好的时候,自己是很自信的,相反,如果系统很慢,有时真不想说这个系统是自己做的。 构建高性能ASP.NET站点之一 剖析页面的处理过程(前端)剖析页面的解析过程 页面的解析过程,这里说的过程不是我们常说的ASP.NET页面的生命周期的过程,而且浏览器请求一个页面,然后浏览器呈现页面的过程。 在本篇的文章中,我会先阐述页面的解析过程,显示从整体上阐述,然后在每一个点上提出优化的方法。先整体,后局部。 当浏览器在请求一个Web页面是从URL开始的。下面就是过程描述: 1. 输入URL地址或者点击URL的一个链接 2. 浏览器根据URL地址,结合DNS,解析出URL对应的IP地址 3. 发送HTTP请求 4. 开始连接请求的服务器并且请求相关的内容(至于请求时怎么被处理的,我们这里暂时不讨论,只是后面的文章要讨论的问题) 5. 浏览器解析从服务器端返回的内容,并且把页面显现出来,同时也继续进行其他的请求。 上面基本上就是一个页面被请求到现实的过程。下面我们就开始剖析这个过程。 当输入URL之后,浏览器就要知道这个URL对应的IP是什么,只有知道了IP地址,浏览器才能准备的把请求发送到指定的服务器的具体IP和端口号上面。 浏览器的DNS解析器负责把URL解析为正确的IP地址。这个解析的工作是要花时间的,而且这个解析的时间段内,浏览器不是能从服务器那里下载到任何的东西的。但是这个解析的过程是可以优化的。试想,如果每次浏览器每次请求一个URL都需要解析,那么每次的请求都有一点的时间消耗,可能这个时间消耗很短,但是性能的提升就是一点点的“调”出来的。如果把对应URL和IP地址缓存起来,那么当再次请求相同的URL时,浏览器就不用去解析,而是直接读取缓存,这样势必会快一点。 其实浏览器和操纵系统是提供了这样的支持的。 当获得了IP地址之后,那么浏览器就向服务器发送HTTP的请求,下面我们就稍微看下这个发送请求是怎么样被发送的: 1. 浏览器通过发送一个TCP的包,要求服务器打开连接 2. 服务器也通过发送一个包来应答客户端的浏览器,告诉浏览器连接开了。 3. 浏览器发送一个HTTP的GET请求,这个请求包含了很多的东西了,例如我们常见的cookie和其他的head头信息。 这样,一个请求就算是发过去了。 请求发送去之后,之后就是服务器的事情了,服务器端的程序,例如,浏览器清楚的文件是一个ASP.NET的页面,那么服务器端就把请求通过IIS交给ASP.NET 运行时,最后进行一系列的活动之后,把最后的结果,当然,一般是以是以html的形式发送到客户端。 其实首先到达浏览器的就是html的那些文档,所谓的html的文档,就是纯粹的html代码,不包含什么图片,脚本,css等的。也就是页面的html结构。因为此时返回的只是页面的html结构。这个html文档的发送到浏览器的时间是很短的,一般是占整个响应时间的10%左右。 这样之后,那么页面的基本的骨架就在浏览器中了,下一步就是浏览器解析页面的过程,也就是一步步从上到下的解析html的骨架了。 如果此时在html文档中,遇到了img标签,那么浏览器就会发送HTTP请求到这个img响应的URL地址去获取图片,然后呈现出来。如果在html文档中有很多的图片,flash,那么浏览器就会一个个的请求,然后呈现。 到这里,大家也许感觉到这种方式有点慢了。确实这个图片等资源文件的请求的部分也是可以优化的。暂不说别的,如果每个图片都要请求,那么就要进行之前说的那些步骤:解析url,打开tcp连接等等。开连接也是要消耗资源的,就像我们在进行数据库访问一样,我们也是尽可能的少开数据库连接,多用连接池中的连接。道理一样,tcp连接也是可以重用的。但是重用也有问题:如果两个图片它们的url地址如下: <img src="q1.gif" height="16" width="16" />
<img src="q2.gif" height="16" width="16" />
<img src="q3.gif" height="16" width="16" />
<img src="q4.gif" height="16" width="16" />
<img src="q5.gif" height="16" width="16" />
<img src="q6.gif" height="16" width="16" />
<img src="q7.gif" height="16" width="16" />
<img src="q8.gif" height="16" width="16" />
<img src="q9.gif" height="16" width="16" />
<img src="q10.gif" height="16" width="16" /> 求这些图片的时间消耗如下图: 大家首先看到最上面的黄线的部分,这个黄线就代表了浏览器打开连接,黄线的后半部分为蓝色,就表示浏览器请求到了html的文档。 最上面的第二条蓝线就表示第一个图片已经请求到了,此时请求这个图片使用还是之前的一个tcp的连接。 大家在看到第三条线,前部分是黄色的,表示请求第二个图片的时候又开了一个tcp的连接,这条线的后半部分为蓝色,表示图片已经请求到了。 剩下的要请求的一些图片都使用上一个tcp连接。 确实,tcp的连接时充分的被使用了,但是图片下载的速度确实慢了,从图中看出,图片是一个个的顺序的下载下来的。整个页面的响应时间可想而知。 如果采用下一种方式,如: 可以看出连接时多了,但是图片的几乎都是并行下载下来的,相比而言就快多了。 其实这就是一个权衡的问题了。 实际上浏览器也是内置了以一些优化方式的,例如缓存图片,脚本等。或者采用并行下载图片的方式,谈到并行下载,就如上图所看到的,势必会消耗更多的连接资源。 今天主要对页面的过程进行了初步的剖析,是的大家有个总体的把握,下一篇我们就开始逐步优化,敬请关注,也希望大家多多提出意见和反馈。先谢过了啊! :) |