http://www.yaosansi.com/post/1150.html
Web2.0网站性能调优实践
文/王宗义
当前web2.0革命风起云涌,web2.0强调服务,而服务最基本的要求是速度快和稳定,离开这两个谈功能强大和易用性都没有任何意义。本文介绍一些关于笔者运营一个web2.0网站的优化心得和经验,希望能够和大家共同探讨。
Web2.0网站不同于以往以静态信息为主的网站架构,以往的结构大体分为2层,一个是客户端浏览器,一个就是web服务器;而web2.0以动态和交互为主,一般是3层或者4层,在静态信息网站的结构上的web服务器后端会增加应用服务器和数据库。一般会把浏览器和web服务器归为最上一层即为web层,应用服务器为中间一层,数据库为最底层。从优化角度来讲,越上层优化获得益处越大,优化也是从上自下而来。
Web层优化
DNS的解析时间
这个时间就是在用户第一次访问网站的时候产生,解析时间会影响用户的访问感受,因此想要网站响应速度快,第一就是不要在DNS解析上产生问题。另外DNS的TTL时间也要考量,IE的DNS过期时间是30分钟,TTL设置的比这个长一点就可以。另外在web服务器上使用keep-live也会减少DNS查询次数。
降低浏览器发起请求的数量
尽量降低浏览器发起请求的数量,就是说尽量能够让浏览器缓存任何可以缓存的东西。这样当用户访问过一次后,第二次访问可能会使得发起的请求数趋近1或者等于1,如果是静态的页面则可能是0。方法包括:
把所有的样式表文件并为1个
把所有的js文件并成1个
图片尽量能够合成1张,这个跟以前不一样,现在大多数是adsl上网,反而是大量的零碎图片能够影响速度
页面布局与样式
页面采用xhtml,采用div+css布局,而把样式表和xhtml文件分开,一则能够降低xhtml文件大小,二则能够对样式表文件进行其他缓存处理。这里还有个ui设计的原则,ui跟系统结构一样,越简洁越好,这样整体页面代码会比较少,速度也会比较不错。
JavaScript文件
JavaScript文件也最好放到html文件外,原因同上。
静态文件的优化方法
a)目前大多数的浏览器都支持gzip压缩文件,因此为文本、静态页面、样式表、JavaScript文件等可以压缩处理的文件进行压缩处理能够减少内容获取时间,一般压缩完的大小为原大小的10-30%。这个在apache等web服务器上进行设置,笔者使用lighttpd的设置为:
server.modules = (
….
"mod_compress",
…
)
compress.cache-dir="/usr/local/lighttpd/cache"
compress.filetype = ("text/plain", "text/html", "text/css", "text/javascript")
b)还可以在静态文件服务器前面增加缓存服务器比如squid,进一步增强客户端的访问性能。如果有好的财力,还可以使用一些商业的CDN加速服务。
应用Cookie的注意事项
Cookie的应用要注意,要限制cookie的应用域和应用的目录以及过期时间。不然如果用户是第一次访问的话,可能连一个小小的静态图片都要发送cookie到服务器,这样增加了通信负载。另外要限制cookie的大小,一个3k的cookie能够增加延迟达到80ms。
提高页面速度
页面由2-4个不同域名的服务器提供服务能够提高速度,这个国外也有研究证明。比如主html文件由app.domain.com提供,样式表由style.domain.com提供,图片等由img.domain.com提供,这样浏览器可以同时从多个服务器下载文件,速度就能够上去。但是最好不要超过4个。
样式表文件位置
把样式表文件放在页面的<head>,这样能够先读取。因为在ie中有个样式表的问题,样式表如果没有加载完会影响后面的html内容的页面显示,因此虽然html文件都已经在浏览器了,但是页面还是显示不出来。
把JavaScript移到html文件末尾
把JavaScript移到html文件末尾。为什么这么做呢,因为JavaScript处理的过程中会阻塞后面的页面显示,并且也会使得http请求也被阻止。笔者的网站就有过这样的例子,网站上放了一个合作方的JavaScript,结果每次访问时候感觉页面都停滞,用户体验特别差,后来让同事处理了一下,放到末尾等页面加载完了再显示在原有位置,一下子就好了。
尽量避免跳转
尽量避免跳转比如301和302。如果必须的话,对301和302的页面添加过期头。笔者原来的单点登录就需要进行跳转,后来改进了不需要跳转,整体的速度效果就出来了。
移除重复的脚本
要移除重复的脚本,ie会对重复的脚本发起重复的http请求,大多数网站在运营一段时间都有可能出现这个情况,笔者的网站中就经常有市场人员添加的重复的广告脚本。
AJAX内容
AJAX内容也是可以进行缓存的,同样可以压缩和缓存异步调用的xml、json等数据。
对爬虫进行限制
对爬虫进行限制,国内的一些爬虫非常厉害,并且不遵守robots规矩,经常有反应某某厉害爬虫把网站搞瘫的事件。怎么对爬虫进行限制呢,只能在web服务器上下功夫了,apache等服务器都能够进行限制,笔者的lighttpd限制10个并发的配置如下:
evasive.max-conns-per-ip = 10
web层的优化目的就是极大的利用了浏览器的缓存特性,从而达到几乎是本地访问的速度,下图是笔者访问douban.com首页的效果图对比:
前一列数据是空的缓存所需要下载的文件大小和http请求数量,后面是真实访问的带cache的情况,效果特别明显。http请求减少了95%,内容cache了82%。
应用程序层优化
应用服务器的优化
Php的可以采用一些优化手段比如Zend Optimizer、eAccelerator、MMCache、Zend Performance Suite等
Java的可以采用一些性能强的jdk、应用服务器,对jdk参数进行优化等等
使用ETag
ETag就像版本控制服务器中的版本号一样,每次更新后的ETag是不一样的,而浏览器处理就类似版本服务器的客户端一样,先把版本号发到服务器请求。ETag的处理过程,先是Web服务器在响应的http头中发送ETag,比如这样:
ETag: "1111-2222-3333"
Last-Modified: Thu, 07 Oct 2007 15:20:18 GMT
而浏览器如果再次请求该页面就会发送类似如下的头:
If-None-Match: "1111-2222-3333"
If-Modified-Since: Thu, 07 Oct 2007 15:20:18 GMT
此时,如果该页面没有任何变更,则web服务器会响应一个304的头,并且不需要附带页面内容给浏览器(即不需要再动态生成页面内容),这样就大大减少了服务器的处理和网路通信负载。
同步变异步
同步变异步,在web2.0网站中经常有很复杂的处理,比如一个用户的注册还需要发邮件等操作,有时候可能还有其他的处理,这样用户的等待时间比较长,并且容易出现错误。此种情况下,把其他处理变成异步的,从而直接把页面尽快响应给用户。笔者的一个数据上传的程序也是如此处理,一大堆数据,上传时间可能就1-2秒,而处理时间可能长的需要接近10秒(需要在数据库中进行上千次的插入操作),而在应用服务器容器内处理耗时则更长,笔者后来改成异步处理以后,用户满意度则大幅上升。
使用缓存
还是缓存,可能的情况下尽量使用缓存,毕竟现在内存非常便宜,用空间换取时间效率应该是非常划算的。尤其是对耗时比较长的、需要建立网络链接的,方法:采用memcached进行数据库或者常用数据的缓存;应用数据库缓冲池减少建立数据库连接的时间
采用gzip压缩动态页面
可能情况下,也可以采用gzip压缩动态页面。如果服务器较多,cpu负载不高,则可以考虑对动态页面增加gzip压缩功能
集群处理
访问压力大的时候,对应用服务器采用集群处理。
应用服务器的优化主要是减少程序处理的时间,提高运行效率。
数据库优化
这个议题跟具体数据库关系比较大,议题也比较广泛,笔者就只简要列举一下:
设置专门的DBA,专门负责数据库的安装、优化;对sql进行优化采用数据库集群和复制功能分担数据库压力。
其他优化措施
网站的优化涉及的方面比较多,其他方面涉及的还包括网站架构、操作系统、服务器硬件、网络设备、isp机房网络等等的调优。
工具
笔者用到的工具,都是firefox插件,所以firefox是必备的了:
1、LiveHTTPHeaders (http://livehttpheaders.mozdev.org/)
2、Firebug (http://getfirebug.com)
3、YSlow (http://developer.yahoo.com/yslow/),要先装Firebug
4、Web Developer (http://chrispederick.com/work/web-developer/)
除了这些免费的工具外,还可以采用一些商业的网站性能监测服务。一般网站性能监测服务商都会在不同的isp设置数据采集点,然后会定期模拟浏览器的访问对网站进行访问获取各种数据,比如dsn查询时间、第一个包获取时间、整个页面加载时间等等,然后汇总到数据中心。数据中心则可以产生性能报表、不同时间的可访问率、哪个isp容易出问题、发出警报等等。如果预算足够的话,可以采用这个服务。国外的有keynote、ip-label等,功能比较齐全,但是服务费用比较贵而且国内的点比较少。国内近些年也开始涌现出一些厂商,比如基调网络。笔者使用的监测系统的图例:
笔者网站3年不同阶段的优化过程
优化的原则是尽量不去优化,在未发生性能问题的时候,没有必要去专门考虑细节的性能问题,当然大的结构应该是能够适应网站不断发展变化的。笔者的网站近3年的优化过程如下:
1、开发完成,刚上线的时候,不做优化,用户量少,用了3台服务器。
2、10万用户的时候,主要对sql进行了优化,还是3台服务器。
3、10万用户到100万的过程中,采用了AJAX等,因此开始关注JavaScript的优化手段,访问量也快速上去,因此对静态文件进行分离并优化。服务器也进行了扩展,扩展到5台服务器。
4、100万-200万用户,业务系统增加了很多,因此数据库采用了复制,程序方面应用了各种缓存处理,在数据库和程序之间增加了memcached进行数据缓存。
5、在200万用户以上,主要在程序架构上做文章,对某些服务使用了集群。另外为了监测国内不同城市、isp的网络状况,使用了商业化的网站性能监测服务。