最近一直在做一个新的线上业务项目,在所有的前期设计,中期的编写以及后期的上线完成之后,开放给用户使用的时候,发现网站的速度没有自己想象中的那么快!于是在经过大量的调研以及调试之后,终于速度上达到了我们的预期。
下面是我这一个多月收集来的一些信息以及自己的一些思考,再次做些记录。
一. 从浏览器向服务器发起请求来说开:
(1).刚开始出现的问题:
刚开始遇到这个速度慢的问题的时候,我在想是不是应该压缩js或者css的一些代码,或者说是加一些内存,加点cache之类的,甚至想到了是不是应该多加点带
宽,反正是一切能提高性能的都应该去做一遍,最终是眉毛胡子一把抓,没有抓到最根本最核心的问题是啥,导致问题解决起来不是那么的容易。
应该考虑的思路:
其实首先应该从浏览器向服务器发起请求这个整个的流程来分析瓶颈,首先需要了解下http请求的过程:
根据http协议,任何一次http请求它的处理过程如下:(ps: 这段是转载的一段)
1、浏览器向服务器发出请求。此时浏览器一般左下角会显示:正在请求...
2、服务器接到请求后调用应用程序(php,java等,根据后缀名确定)执行。服务器接到请求后会马上返回一个头信息给浏览器,此时一般浏览器左下角会显示:已经连接
到服务器(服务器接到请求)
ps:如果速度很快,浏览器左下角这些信息是一闪而过的。如果网络出现延迟,这些信息会一直显示在左下角位置。
3、php,java等代码执行完毕
4、代码执行完毕后,服务器会发一个http头响应浏览器(也就是告诉浏览器你开始接收数据了,准备好吧)。
此阶段浏览器在没有接到这个头信息之前,左下角会显示:正在等待服务器响应...
5、浏览器接到服务器发给响应头,开始接收了数据,浏览器处于接收数据状态,
我们会看到浏览器左下角会显示:正在传输数据....。也就是这个状态。
6、传输数据结束,完成一次http处理,整个过程http处理结束。
浏览器归纳左下角的状态依次为:正在请求》》已连接到服务器》》等待响应》》服务器已响应》》正在传输数据》》开始渲染数据
其实我们可以从这六个阶段分析出来,到底是那块比较慢,大体来说:
第一个阶段: 正在请求,这个阶段如果慢的话,可能考虑是不是带宽的原因,是不是服务器机房不在国内导致的,比如中国到美国的光缆就是通过大西洋的海底光缆进
行通信的
第二个阶段:已经连接到服务器,说明此时的服务器(apache或nginx)已经开始调用相关的php或者java的模块进行处理了,此处应该没有性能的影响!
第三个阶段:等待响应,此时如果速度过慢的话,就应该引起重视了,可能是自己的程序上写的有问题,需要对相应的代码块进行基准测试,具体的最简单的方法就是
使用microtime_float这个函数,来
进行测试(ps :此函数的基本用法在php的手册上都有),在代码刚开始的时候,放上一个时间,结束的时候放上一个时间,然后两次时间相减就是耗费的时间,具体的
代码如下:
1 $begin_time = microtime_float();//执行开始记录时间戳,精确到毫秒 2 3 /*中间要执行的代码*/ 4 5 end_time = microtime_float(); 6 7 $exec_time = $end_time-$begin_time;//执行时间计算 8 9 @save_stat($exec_time);//把执行时间写入到文本文件中 10 11 12 /*下面是定义的两个函数*/ 13 function save_stat($time) 14 { 15 static $call_count=1;//统计调用多少次 16 $call_limit = 10;//遇到并发问题的时候限制尝试多少次 17 if(!$time) return ; 18 $exec_stat_file = "./exec_stat_file.txt"; $fp = fopen($exec_stat_file,'ab'); 19 if(flock($fp,LOCK_EX)) 20 { 21 $s = 'access:'.date("Y-m-d H:i:s").',execute time:'.$time.'s,request_url:http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']."||".PHP_EOL; 22 fwrite($fp,$s); 23 flock($fp,LOCK_UN); 24 }else{ 25 usleep(1000); 26 if($call_count<$call_limit) 27 { 28 $call_count++; 29 save_stat($time); 30 } 31 } 32 33 @fcolse($fp); 34 //var_dump($fp); 35 36 } 37 38 function microtime_float() 39 { 40 list($usec, $sec) = explode(" ", microtime()); 41 return ((float)$usec + (float)$sec); 42 }
注:这个时间包含了数据库的sql的执行时间,如果是大于2秒的话,我觉得就是有点慢了,那就要仔细的分析此处的代码,是不是不该循环的使用了循环,是不是算法
使用的不是很准确?
这是程序方面的,那如果这个都没问题的话,我们在看下是不是数据库的SQL写的有问题,将每个SQL放到数据库中执行一遍,统计一下消耗的时间,是不是需要进行
一步的优化,该怎么优化?这块是
一个比较大的话题,这块稍后做记录,此处只是聊一下思维上的东西。
ps:我们在做测试的时候,需要多测试几回,最终求一个平均值,可能由于一些非人为的因素,一次的测试结果可能没有那么的准,因此需要这样!
其实这个阶段最容易出现问题,因为这块涉及到程序设计问题,数据库的设计问题,这些都是我们在定位到问题之后,需要细化的一个方向!
第四,五个阶段:那如果前面三个都没有问题的话,到此阶段,说明正在传输数据,如果执行慢的话,考虑是不是带宽的原因,是不是应该加带宽这样的问题!
第六个阶段:浏览器拿到数据后,开始渲染数据,此阶段执行慢的话,考虑是不是在前端用了过多的插件,导致的。(ps: 我们再上线这个项目的时候,所有之前的步
骤都没有问题,只是到这步得时候
,渲染数据变得特别的慢,最后发现使我们使用了太多的第三方的插件,这个也是有时间消耗成本的)
上面的这六个阶段,只是粗略的整体分析了一下,我们在做调试的时候,我觉得是需要有这个大概的路子的,依照这个方式慢慢的往下追,总能发现问题的瓶颈在哪
里。
自己刚开始调优的时候,想的确实挺多的,但是都没有抓住到瓶颈的问题在哪里,只是优化了一下一些无光痛痒的地方,导致速度也没上来。
我们在优化的时候,我觉得需要做到的是:
找网站目前性能的瓶颈在哪里,把瓶颈解决了,其他方面细微的影响速度,也是很小的.如果不去找瓶颈,把细微而非主要的矛盾去解决了,但由于瓶颈没解决,整个
速度也不会快.
其实在整个流程过程中,程序方面,只是优化了一小部分,在数据库方面的优化,算是真正的提高了整体的速度,所以下次记录下数据库层面的优化!