###################################
方法与观念的改变
###################################
错误导向:
我在网上会看到人们怎么优化网站,就是用yslow这样的工具来看,工具会告诉你要怎么做,哪方面有问题,比如我写在文档里面的像这样的:
这里会告诉你要开启压缩。
这里大致反映出时间。
这些做法做都是正确的。只是这种都是花俏的工夫。把这些当成是优化的方向,方向不对。着力点错了。结果发现网站速度没明显改善。因为方法错误了。基本是这种想法:先按照上面说的,把该做的做了吧。肯定有提高的。始终没尝试找网站速度慢的瓶颈在哪里?
同学总结得很恰到:这些工夫无非是合并多个js,css文件。该压缩的压缩。能少占用带宽资源。但是都非关键点。去优化关键点,留到后面优化。
什么是瓶颈?
我以前没想到比较通俗的方式解释。通俗点,就是瓶口的大小。瓶子的口子大小就那么多,已经决定了一次只能进那么多量。假如发现一个方面就是限制最大的因素。把这个主要矛盾解决就ok了。假如数据库是瓶颈就解决这个问题,假如磁盘速度是瓶颈着力点就解决这个。
一个形象的比方:一个木桶,有一块最短的木板,就算把其他板块加的再高,整体装水不会多。木桶的瓶颈就是最短的这一块。
技术上的例子:cpu用得再好,把二核的改为四核,php脚本速度提得再高(装代码加速器,去掉一些模块),apache性能再好,内存提到到8g。数据库优化到再牛逼。网络口子就那么多大,距离这么远,传递的数据量有限。就算你apache在0.01秒就能丢给数据给浏览器。但是网络影响,要请求图片,css文件速度怎么都快不了的。网络是我们目前的瓶颈。cpu速度,内存等等目前都不是木桶的短板。优化在快也改善不了本质问题啊。
一根水管的管道就那么点大,即使你在怎么提高优化其他方面的,虽然有好处。但是仍然没有明显改善。
性能与优化的分析方法:主次矛盾。技术上就是说找到瓶颈所在。把瓶颈突破,其他问题都不会成为障碍了,整体就能达到预期目标。
我亲身经历的一个例子:技术经理是79年的。其实我们的网站访问速度还不错。而老板看到同行的网站网站怎么快些。(人家才多少个技术,我们这么多。应该要达到)。
技术经理把一些方法都尝试了:研究同行的no-cache头,唉,他们的怎么有,而我们的没有。好,我们也要像他们那样做。我们还把代码片段给缓存起来,花了不少时间。可惜,结果速度没有明显提高。有,也只是根据感觉:“哦,我刚才加了缓存控制后,发现服务器的负载低了点。但是怎么又变高了呢。”。“我已经开启了压缩,怎么没明显改善呢?”,其实,加服务器缓存控制,代码判断缓存。肯定是有效果的。但能提高多少?或者说目前这个不算瓶颈。就算你把其他的优化得再好。也没提高整体。没找到瓶颈所在,结果各自方法都试过了。还是没用。白忙活。如果一开始能够分析出瓶颈。着力点完全不同。
因为不是专业的运维人员,所以,我们不知道怎么去分析性能瓶颈。只是根据感觉,这样做可以提高点性能。先这样做吧。
discuz的人说,“(技术经验)价值连城”。我现在确实有这种感觉,经验就是财富。别人与你非亲非故,干嘛要把经验告诉你呢?我们能看到的仅仅是网上的资料,书籍。这些我发现要形成自己的经验才是关键。比如,大部分建议要apache开启压缩,合并js,css文件。基本上是参照国外人的这本书,我看过:《高性能网站建设指南》。
这上面说的这些都是正确的做法。
由于没人传递一个分析方法。所以,一遇到网站性能问题,往往是先参照网上的,书籍的建议,把基本点做了。然后在考虑对策。比如我经理,仍然是凭着感觉去尝试各种方法。如果一开始就能够分析出瓶颈所在。就不会无效果了。他不是专业的运维,确实也没这方面的分析经验。只能是瞎耗费时间了。试10个方法都不会有突破。
我现在发现,这些都是一些小技巧。谈不上解决瓶颈问题。书的标题就写明了,针对前端工程师的。如果你按照上面的各种方法:压缩js,压缩css。控制缓存。发现自己网站的速度却没明显改善。可能此时你网站的瓶颈在于数据库或者说是带宽,这方面瓶颈没找到,或者不解决,一直感觉不到整体提高。
有些人会告诉我:先把基本点,也就是能做得做了吧。然后在考虑其他提高。这其实是道理。
我发现以前我真是这样的。压根就是没有分析瓶颈的一种导向。比如,网站速度很慢,你说,我先把基本点做好:cpu,数据库优化,内存。可惜这些都不是瓶颈。做了确实比不做好。但对问题没效果。
后来发现:做有些事情,确实是要先把基本点做了。然后再去考虑。而有些事情,基本点做了根本影响不大。因为不是瓶颈。找到主要矛盾解决,其他的都不算问题,在慢慢优化。
谁都知道做了那些基本点有好处(看书,网上资料),但是有经验的人才会告诉你真实的答案。我经理79年,做了至少8年技术。对于分析瓶颈方面并没有经验,只能是各种方式试一下.不见效果。
曾看过阿里巴巴的简朝阳的《myql性能调优与架构设计》,里面分析优化sql,一个思想让我印象深刻:分析一条sql,先分析出瓶颈所在。这样能确定一个预期优化目标。如果没分析清楚,感觉这样能够提高点。就把各种方式都尝试了。结果还是没优化。
我以前还真是这样的:拿到一条sql要优化,我就凭着感觉,这样做会好点,哪怕是能够改善0.001s的速度都行。先这样尝试吧。然后没明显改善,又去用其他方式尝试。如果这样改写下去,几十次都没达到速度提高。尝试得头晕都不会有改善。或者改善了也是碰对了。
比如说:拿到group by,反正根据网上group by如何优化,试一下。其实如果搞清楚group by的原理,对比一下查询的数据量。发现它根本不是sql的瓶颈所在。尝试了等于是浪费时间。
我注意到,合并js,压缩是对的,但网易并没这么多,它的js文件内容我打开看,还是原始状态的:
网易服务器虽然n多,性能非常好,带宽虽然多。合并,压缩js和css都是正确的做法,能提高速度,而他干嘛不做?如果一个事情是一个关键点,他们必须会做的。结论是,他们明白这个根本不是网站的瓶颈所在。纠结这些还不如去纠结关键点。
有些大网站,确实也对js,css压缩合并了。合并js,css确实能够提高。有好处。但我还从没见过靠这种方式把网站速度达到一个质的提高。他们是:先把瓶颈突破,其他基本点后面在做,到时候可以做可不做。影响不明显。
常常碰到这种的方向错误:
比如,数据库去优化,修改字段之类的。虽然能够提到速度,但是在数据量这么小的情况下,竟然速度访问慢。数据库肯定不是瓶颈,这方面的改善无法都无法解决根本问题.结果速度还是慢。
比如,网上一直流传php的代码性能差异之比
例子1:
echo $a.$b.c;
有人认为这样写性能更高(确实是,省去了符号.进行逐次解析):
echo $a,$b,$c;
例子2:
echo "this is {$tile}"
优化成:'this is'.$title;//把变量放在""符号之外,是可以省去解析时间
无法说上面的优化是错误的,而且确实要承认那样去优化性能会更高。但是真的要问,到底性能高多少呢?高0.0001s,这种优化有改善,但意义多大?
这种优化压根就谈不上瓶颈。假如:php把10万条数据一次读入到内存,发现卡死了。这就是php代码处理的瓶颈(实质上是内存问题),此时优化代码逻辑就可以解决根本问题。少操作些数据ok。想把内存提高不靠谱。
纠结,细扣一些花俏,影响不关键的方面。总不会有多大改善的。网上经常提到那种,php代码优化的10个方法。人人奉为圭臬。扣得太细了。当瓶颈不在这里的时候,优化不了多少。
php代码的这种优化,我以前也是去纠结过。但是后来发现,没有找到瓶颈所在,所做的工夫都是白费的。
别人其实也犯这种错误。
我遇到这样一个例子:我以前上面分配一个优化后台某项统计数据的查询。但是因为不懂得抓瓶颈问题。没有明确的方向,我大体方向只是在优化sql查询上做改善。其实方向是对的。瓶颈确实是在数据库方面。但数据结构设计,再好硬件,sql优化再好,统计查询都快不起来。
折腾了很久,同排一同事想帮助我,他的方向完全不同,他的着手点也是改善php代码:他把php处理的循环方式改善一下,比如原来是怎么循环的,改成另外一种循环方式。其他代码也进行改善代码。
其实通过这个事情,我发现没有理解瓶颈所在,就在那个时候我明白了:同学告诉我,php的处理速度已经非常快了。整体看执行时间慢,它是一直在等待数据库给予数据。所以脚本就很慢了。所以那么大的数据查询统计,也许像上面例子那样去改善,纠结一些次要的东西。无论怎么优化代码,都解决不了统计查询速度慢的问题。着力点要搞清楚为好。
服务器的php程序执行速度非常快,执行完后就发送数据了。服务器在美国,假如在中国访问,距离这么远,再快也快不到哪里去的。
也许就有疑惑了。这个网站也是在美国:http://digg.com/
怎么访问速度那么快?
这个网站他肯定在中国部署了服务器的。比如阿里巴巴想保证全国各地的用户都能访问他网站。他如果把服务器全部放在杭州,或者全部放在北京。南方的人访问,光是距离也要那么远。根本不会有现在这个速度。所以,距离如果远:服务器本身性能再高,速度也快不到哪里去。所以先把脚本的执行时间统计出来,这样便于确定服务器消耗。
ps:有那些cdn加速服务需求,单双线机房之分。就是通过解决距离远,时间延迟上的问题。
我在英国,访问美国服务器。能快起来吗?
看这个博客:blog.strabbit.com,服务器是美国的一个vps。看在中国访问速度如何?
网站的访问速度是一个多方面导致的因素。
我首先会去判断程序执行的性能方面。做一个严格的执行时间统计。这么做的作用是:确定瓶颈在数据库响应数据,还是在程序执行性能, 还是在网络带宽因素?
我放一个统计脚本也是想统计出程序每次执行的准确时间。
统计的机制是这样:
在程序执行开始执行时记录一个时间,结束的时候定一个时间。结束时间减去开始时间。就是php脚本所执行的时间了。在并发访问不多的情况下,脚本的执行时间会在稳定范围内。
这样做也是根据一次请求执行的原理来的:
1、浏览器进行http请求
2、apache处理:
if(请求的为php脚本)
{
apache丢给php引擎处理
php执行生成html给apache,nginx等服务器》》
}
else
{
图片,静态html页面,js等静态内容.
直接从磁盘读取文件结果给浏览器
}
3、apache将html结果通过网络发给浏览器。浏览器解析html,渲染出结果给用户看。
把这个过程搞清楚了。定位问题就不会错误去估计:统计出php脚本时间。就明白apache多久才从php拿到html结果。
php程序的总时间大体反映出了:php向mysql获取时间,和本身执行所花费的时间。
我注意过一点:php连接mysql请求数据。如果mysql负载高,响应不过来。那么php程序就会处于一直等待mysql返回数据状况(这就是时间耗费,常常导致在浏览器请求页面的时候速度很慢)。
所以,为什么首先要统计出php的执行总时间了。假如:我请求index.php页面,统计出php的脚本执行时间才0.05s(秒)。但是偏偏在浏览器访问的时候,发现速度慢的不行,一直看不到结果啊。根据上面的http请求过程和apache,php之间的关系。php脚本生成html结果早就给apache了(这个时候已经完全脱离php处理,php处理引擎任务完成,我只负责查询数据库最后生成html而已。执行到这里的时候如果速度快.已经脱开数据库性能,php脚本性能了)。
而index.php返回的html内容中可能包含其他http请求。像这样的元素:
<scritp type="text/javascript" src="jquery.js"></script>,
<img src="http://piwik.shophairextensions.co.uk/piwik.php?idsite=1" style="border:0" alt="" />
<link rel="stylesheet" type="text/css" href="http://www.shophairextensions.co.uk/media/css/454f62d8439826741663bd9757fc0d3d.css" media="all" />
浏览器渲染apahce返回的html结果后,如果遇到像上面的标签,浏览器就会继续像服务器请求文件。
html结果早就能得到了。而我们看不到结果,因为数据没有传送完毕,服务器已经完成他该处理的事情了(处理完正在发送数据了)。网络状况的话,与服务器性能有什么关系?所以经常发现这样的情况:
图一
图二
浏览器请求的时候,左下角一直显示“正在传送数据“。其实此时php解析早就完成了(此时稍微注意,偶尔查看浏览器源码。往往发现能够看到html结果了,前提是html通过网络已经完全传到浏览器端了)。或许网络原因,一直停留在服务器与客户端发送数据过程耗费时间。
如果显示"正在等待响应....",那说明服务器还没有给数据给浏览器。可以做个试验:
用个php文件,代码里面循环10万次。看浏览器怎么反应
for($i=0;$i<100000;$i++){
for($j=0;$j<200;$i++){
}
}
搞清楚http请求的过程,定位就容易点。
第二张图片:一直没看到结果。页面一片空白。能说是服务器性能不够好吗?能说瓶颈是要优化php脚本吗?其实这个时候也已经生成好html了。服务器正在给客户端发送数据,网络原因,延迟。
浏览器左下角:有时候显示的是正在连接网站,可以分析出的意思不同。我常常遇到数据库大数据量的时候,一条sql查询了很久,响应出现问题,所以php就一直在等待数据。那么apache,nginx根本没得到php的处理结果(也就是说php脚本耗费时间太多,根本没执行完)。此时在浏览器看到是”正在服务器等待响应"。
脚本的执行时间大体上是固定的变化不会太多。所以能够通过在php的开始的和结束的定时间参考php脚本的执行性能。
但并发访问越多,脚本的处理速度就越会受到影响:
php脚本的执行时间统计往往能够定位脚本处理,数据库性能方面问题。比如,并发访问大的情况下,假如1000个并发(如同时在0.001秒刻进行访问,网站用户多的时候,这种情况经常碰到,测试时是通过压力测试工具才模拟得出来)。
运维常常设定一个类似于这样的预期目标:模拟在10000并发的情况下,看看服务器负载情况,脚本响应时间要控制1s之内。而在浏览器要保证2s以内看到整个页面(页面的附带请求忽略掉)
##########################################
分析结果
##########################################
对浏览器http请求,apache处理,php,mysql之间的关系越了解就越能确定原因所在。
注意到没有:hairextensionsclipon.com,ebesthair.com这两个网站都是加了php代码加速器的.平均每次页面的执行的时间是0.2-0.8s之间。但是如果发现,在
浏览器是等待了4-5秒才完整显示出结果的话。
就把这5秒减去0.8s。就能知道时间花费在哪里了!能够大致预估的。
可以做一个试验:把首页保存成一个静态html文件。放到服务器上。然后在中国直接访问这个静态html。
这样做的依据:静态html是完全不需要php解析,数据库消耗,这就可以把解析时间排除掉(我做php统计执行速度也是想做参考)。apache拿到静态内容直接发给了浏览器。所以可以完全测试出网络传输速度如何!
要逼真的模拟,可以这样做:打开首页》》查看浏览器源码。把源码保存起来成一个html文件。
这样做的好处是,这个静态页面,其中也就包括一些js,css,图片的加载。完全逼真模拟。
我们常常看到:访问一个网站。浏览器已经显示出html效果了。但是布局却是乱的(没有css效果的那种,实际上就是css文件没加载完)。或者图片位置是空的。
往往需要等上一段时间页面布局正常。什么原因?
这里能够确定:html页面结构(一个完整的html代码,并不包括src属性要载入图片和js文件内容,style标签要载入的css文件等)已经通过网络完全发送到达浏览器。浏览器已经正常的解析了!只是style标签要载入的css文件还没达到而已。网络速度延迟了。php要做的事情就是上面这一步:它给apache的结果就是html,apache会发给浏览器解析,浏览器解析才看到了最终的效果(所以js文件,css文件只要已经网络传输到浏览器端,执行都是耗费客户端内存,cpu资源了)。
根据浏览器的解析原理:比如访问首页,浏览器拿到apache发给它完整的html代码。才会进行解析,渲染出页面的基本结构。是先渲染出整体结构,然后才会去加载页面中需要的css文件,图片,js文件。
所以这里就里问题就出来了:即使你网站的处理速度快到0.1s。但是带宽不行,或者我这边网络速度慢,仍然会出现,浏览器一直显示“正在在传送数据”。这个时候说明,php早就已经生成html结果给浏览器了。通过观看浏览器的表象就能大致确定哪一段才是瓶颈所在了。比如,我曾经遇到下面情况就不是网络原因:
在浏览器访问一个自己写的php脚本,该脚本要对一个数据库的数据进行更新。数据量太大了,php执行时间很长。浏览器会一直显示,正在等待响应,这个时候,连数据都没传递到浏览器。就是因为:php一直没处理完,没有给apache结果,apache也就一直等待中了。
我的建议是,apache缓存控制,js,css压缩都是可以做的,这些确实可以占有网络资源.但是这个放在后期去做。因为就像木桶一样,你再怎么做其他方面,忽视短板是无法提高的。结果速度还是慢。不信可以尝试.现在你再怎么提高,都突破不了网络的限制。带宽只有那么多。如果在中国访问,这么远,怎么都快不了。
我观察和分析了几天,瓶颈就是:网络原因(包括了带宽,距离远访问)。网络的速度最终影响了数据达到客户端的耗时。
硬件:包括cpu,内存方面不是瓶颈。即便弄台独立服务器也是一样的.
数据库:几百万条数据,如果是查询单条商品都是0.00x秒级别的(因为是索引关联速度很快)。我们才几百条商品数据,数据量小的可怜.查询慢不到哪里。分析认为不是瓶颈。
程序:magento往往给人一种运行速度慢得像乌龟的印象。所以会错误认为这是瓶颈。把模块优化一下。magento在本地电脑确实慢,统计的时候执行了5s-6s。但是pc机子与服务器硬件配置上是不同的:
其实,cpu的处理速度很快,内存的速度已经非常快了。一般性能最大瓶颈就是i/0能力(磁盘,这也就是为什么需要memcached之类的东西)。磁盘的读取数据快慢起到决定作用,延迟.尤其是大访问,并发访问的时候影响就更明显了。服务器的硬盘转度比pc快很多。一般为10000转/分钟-15000/分钟。pc机一般5400/分。转速越快,i/0能力就越好,给用户反应就是拿数据越快.
所以,统计发现,magento放到服务器上,往往执行时间很短了.虽然服务器的cput,内存比pc机都要配置高。但并不是因为cpu,内存的缘故而速度快.
注意到没有,加了代码加速器脚本执行时间很短了.包括查询数据库到最后给html给apache。总时间不超过1s(有时为0.2s)。如果再优化确实有空间。但为后期做的事情。不是解决速度的瓶颈。
方案:
一,主机距离部署近点访问客户所在国家。针对英国客户为主的,购买主机就一定要部署在该国。部署在美国怎么访问都快不了。浪费财力。
我们访问digg.com,其虽然在美国,但是速度快。那肯定是在中国附近部署的服务器(cdn加速服务)。很多国外网站是在新加坡部署。
二,提高带宽资源。向空间服务商加钱就可以加带宽。
关于这点,如果主机部署较远,即使你带宽再多,恐怕不会快到哪里去:
国与国之间的网络肯定要比本国内各个省份之间的网络繁忙得多。毕竟是一国所有向外数据的通道。比如中国与美国网络通信,是通过东部海底光缆联系的。意味着整个中国通向美国的数据访问都是经过同一道线路的。
三、服务器在美国,美国人也访问慢的话。与这种情况类似:假如在南方城市长沙,访问服务器在北京的网站。速度慢往往是距离远的导致传输数据时间变长导
致的。因为在并发量不大的情况下(我们网站的并发访问量小之又小),php脚本执行的的时间是稳定的范围.所以,与服务器性能关系不大.
如果考虑购买cdn(内容分发)加速。在临近用户访问地部署节点,图片,css,js进行。虽然有效。但经过综合权衡,问过一个有经验朋友,这样做还不如把钱投入到带
宽增加上。这样花钱也花在刀刃上为好。
附:总结的测试网络带宽速度的技巧
一、看ping值。快的一般是几十毫秒。
二、丢一个文件,静态文件,放到服务器上。打开浏览器访问,看下载时间。
比如,放一个100m的文件放到vps上,直接下载,看每秒多少k的速度。
一般一个网页预算200k。按照每秒多少k计算,就能确定一个网页网络达到客户端需要多长时间。实际中是要加上服务器脚本的执行时间。
三,因为我在中国,访问美国的vps肯定受到网络距离的影响较大。假如客户是美国人,如果想测试美国人访问自己的vps速度如何。通过一些工具网站的测试工具往往不靠谱.一要保证该网站与vps在同一国.不能工具网站在加拿大,而访问美国的vps.跨国了,这种方式无法得到真实可靠的数据.
可以准确测试的方式:登录到所在某国所在电脑的远程桌面,然后在远程桌面上访问vps上的网站,看用了多长时间.
或者:一台服务器在a国,取一台a国所在的另外一台vps,在vps上写一个php脚本去vps上下载数据,统计时间长短.也可以使用shell命令,wgets,会告诉你网页传输总时间。
2012-05-10