前段时间做了一个PHP(TP框架)的项目,同时整合了Ucenter与Discuz论坛打通,实现了同步注册与登录,开发过程中遇到的各种问题,好在一一解决,结果最终上结之后出现了意想不到的情况,访问速度奇慢,虽然当时服务器配置低了些(windows server 2012 1核 2G 1M带宽 phpstudy搭建的环境),但也不至于慢到如此地步,打开页面都要卡三秒,而访问论坛模块的速度却很快,于是在代码中找各种原因,去除所有非必须的SQL、启用GZIP压缩、压缩CSS/JS文件、启用CSS/JS/Image文件缓存、均没有太大的效果,只有在开启了静态页面缓存之后速度才有了提升,静态缓存是以空间换时间的一种方案,但也有一定的弊端,若公共页面中包含用户登录相关信息,若设置的缓存有效期过长就会出现会员信息混乱的现在,即我的账号登录了个人中心,会出现别人的信息。这种方案适用于一些网站文章页面及一些不常变化的页面,而不适合于个人中心这类页面。
解决了不常变化的页面速度问题,接着就是解决个人中心这类每个人访问页面信息都不相同的页面,在一些页面上启用了动态缓存这后第一次访问速度依然很慢,而在第二次打开页面时速度便有了明显的提升,在没有缓存的慢冲下再看打开链接的时间记录,仅网站链接做出响应所用的时间就占用了1S-2S的时间,于是将问题所在锁定到数据库上,在调整了所有的参数之后,速度依旧,尝试服务器本地访问速度依然不增,于是想到了配置文件,配置文件是在本地上传后修改了服务器的用户名和密码直接使用的,与Ucenter及Discuz的配置文件数据库链接部分对比,唯一的不同点就是ucenter与Discuz定义的host为127.0.0.1而TP网站定义的为localhost,在此之前看过一些文章也提过这种情况,说使用localhost与使用127.0.0.1在速度上的影响很大,于是我看了一下服务器的HOSTS文件,发现里面并没有将localhost定向到127.0.0.1的本地回环地址,正是由于DNS解析的时间造成了服务器响应慢的现象。这才找到真正的原因所在。将配置文件中的localhost换为127.0.0.1之后速度便恢复了正常。
在对网站的优化过程中收集了各路大神以及官方资料,在此稍做整理。
1.网站响应时间
网站响应时间一般使用首字节到达时间来计算。
一般来说访问网站是通过HTTP/HTTPS请求来完成的,HTTP协议是无状态的,同一客户端第二次访问同一个服务器上的页面时,服务器并不能通过访问链接或协议得知该客户端是否曾经访问过,这种不记录状态的方式使得服务器能支持大量的HTTP请求,HTTP是利用TCP协议来通过两台电脑之间的通讯的,而建立TCP连接需要经过三次握手,关闭TCP连接需要四次握手,因此作为无状态的HTTP连接来讲,建立连接所花费的时间是很大的。HTTP1.0使用的是非持久连接,每次请求都要重新建立新的链接,这使得页面下载变得很慢,同时也加重了网络负担;而HTTP1.1开始使用KeepAlive持久连接的,即在一定的时间段内保持连接,可以在一个连接中完成多次数据请求与响应,在这种情况下,服务器响应完成后并不会直接关闭连接。这样就减少了建立连接的次数,节省一部分时间,同时减少带宽的占用。
而要完成http请求,就需要DNS域名解析,DNS将域名解析成IP地址,再通过IP地址找到服务器,才能让服务器做出响应。一个快速的DNS解析服务器也是影响网站访问速度的重要因素,DNS解析越短,服务器接收到请求越快。
因此网站的响应时间(首字节时间)大致等于DNS解析的时间+TCP三次握手的时间+HTTP请求的时间+服务器处理响应时间+响应数据返回时间。
在这些因素中我们可以提高的有DNS解析时间,服务器处理时间。
2.优化DNS解析
一般经优化的网站DNS解析的时间可以控制在200MS左右,若带宽达到100M可以在50-100MS,对于DNS的优化这里不做重点,主要通过几个方面来控制:首先利用TTL,尽量让用户直接从运营商的DNS缓存中得到A记录,其次选择用户量大服务面积广的域名解析商;最后学会使用CNAME。
3.服务器处理时间
这里的服务器处理时间是我们主要要优化的地方,服务器处理可优化的地方主要包括:服务器硬件升级、服务器操作系统选择、服务器环境工具的搭建、数据库的优化等
3.1 服务器硬件升级
首先硬件升级的效果是立竿见影的,主要包括CPU、内存和带宽,选择一个适合自己的配置很重要。
3.2服务器操作系统的选择
常见的服务器类型有windows系统和Linux/Unix系统,其中Linux/Unix系统一般不安装图形界面,系统本身战胜资源较少,一般通过命令行来管理,这就要求开发人员对基本的shell命令有所了解。而windows操作系统默认是安装了图形界面的,系统占用的资源较大,同时其稳定性较Linux/Unix差一些,宕机的可能性较大,但图形界面管理比较容易。
如何选择服务器操作系统要在满足自身需求的同时考虑到环境是否真正适合自己。
3.3 服务器环境的搭建
环境的搭建与配置也十分重要,如果使用Linux系统可以搭建LAMP或者LNMP甚至LNAMP的环境,如果选择windows系统则可以使用IIS或者另外搭建Apache/Nginx的服务环境,nginx的并发性较apache要好,而且节省资源,apache的rewrite稳定性较nginx要好,而且模块较多,一般来说需要性能则选择nginx需要稳定选择apache.(观点较为片面)
环境搭建的同时要考虑到影响网站访问速度的一些配置信息,包括js/css缓存文件的配置,将不常修改的信息设定一个较长的缓存时间,这样用户二次访问的时候不必再次请求相关文件,只需加载新的数据即可;配置GZIP压缩,通过GZIP扩展启用GZIP压缩可以将CSS/JS/IMAGE等较大的文件压缩到较小的体积,减少带宽的占用,提高访问速度。
配置缓存,如memcache,Xcache, redis等。Thinkphp自带S函数可实现动态缓存,这些缓存的配置最好在开发初期就考虑到使用哪种,以免后期添加对代码的发动较大。
3.4 数据库的优化
避免开篇提到的那种情况 上线配置一定要定义为IP地址。
3.4.1 尽量使用存储过程,存储过程属于预编译语句,经过一次编译之后不需再次编译,只要传入相应的字段值即可,减少了SQL语句编译的过程。为常用操作添加存储过程可减少大量SQL执行时间,提高执行效率。
3.4.2 为搜索字段建立索引,在有索引的情况下能大量减少查询时间
3.4.3 尽可能使用NOT NULL来填充字段,并减少使用WHERE判断NULL值。通过Mysql官方文档得知NULL值要比正常值多占用1bit的存储空间。
3.4.4 数据库表的大字段剥离,保证单条记录的数据量很小,可将表分区或拆分,将一些常用经常更改的信息存放到一张表中,不常修改的信息存放到另外的表中,并减少JOIN语句的使用。
3.4.5 减少字段冗余。
3.4.6 可使用NoSQL
3.4.7 减少全局扫描
3.4.8 尽量避免or来连接条件,可使用UNION语句来代替
3.4.9 用exists代替In
3.4.10 避免使用游标
3.5 PHP中需注意的几点
3.5.1 用单引号包含字符要比双引号快,用双引号时PHP会搜索字段周围的变量。
3.5.2 用foreach 代替for 或遍历前计算好遍历长度,避免每次都要计算。
3.5.3 地访问链接若为目录后面加上反斜杠"/",若不加反斜杠服务器会先判断要访问的是目录还是文件,再定向到目录下的index.php或index.html等文件中
3.6 前端需注意的几点
3.6.1 减少页面请求,合并CSS/JS文件,尽量将所有的CSS代码放到一个CSS文件中,JS也是同理,上线后应压缩相关文件
3.6.2 将CSS放在头部,JS放在尾部,在加载完样式的前提下再去提高用户体验
3.6.3 使用CDN加速,对于常用的如JQuery等相关文件使用CDN加速
3.6.4 图片尽量使用height width属性,避免图片加载完成后界面二次渲染
3.6.5 适当使用AJAX,并不是AJAX使用越多越好,要根据实际情况选择使用AJAX
附:apache开启 GZIP 相关配置
http.conf文件中找到
LoadModule deflate_module modules/mod_deflate.so
LoadModule headers_module modules/mod_headers.so
去掉前面的#号,并在conf文件或.haccess文件中加入如下代码
<IfModule mod_deflate.c>
DeflateCompressionLevel 6
SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/x-javascript application/javascript application/json
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary #设置不对后缀gif,jpg,jpeg,png的图片文件进行压缩
SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary #同上,就是设置不对exe,tgz,gz。。。的文件进行压缩
SetEnvIfNoCase Request_URI .(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzip dont-vary
AddOutputFilterByType DEFLATE text/* #设置对文件是文本的内容进行压缩,例如text/html text/css text/plain等
AddOutputFilterByType DEFLATE application/ms* application/vnd* application/postscript application/javascript application/x-javascript #这段代码你只需要了解application/javascript application/x-javascript这段就可以了,这段的意思是对javascript文件进行压缩
AddOutputFilterByType DEFLATE application/x-httpd-php application/x-httpd-fastphp #这段是告诉apache对php类型的文件进行压缩
BrowserMatch ^Mozilla/4 gzip-only-text/html # Netscape 4.x 有一些问题,所以只压缩文件类型是text/html的
BrowserMatch ^Mozilla/4.0[678] no-gzip # Netscape 4.06-4.08 有更多的问题,所以不开启压缩
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html # IE浏览器会伪装成 Netscape ,但是事实上它没有问题
</IfModule>
apache 开启图片JS/CSS等文件缓存
加载mod_expires模块,conf文件中找到如下代码并去掉前面的#号
LoadModule deflate_module modules.so
在.haccess文件中加入如下代码
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault A600
ExpiresByType image/x-icon A2592000
ExpiresByType application/x-javascript A2592000
ExpiresByType text/css A604800
ExpiresByType image/gif A2592000
ExpiresByType image/png A2592000
ExpiresByType image/jpeg A2592000
ExpiresByType text/plain A86400
ExpiresByType application/x-shockwave-flash A2592000
ExpiresByType video/x-flv A2592000
ExpiresByType application/pdf A2592000
ExpiresByType text/html A600
</IfModule>
关于memcached提供一个链接Install, configure, verify memcached on CentOS http://devdocs.magento.com/guides/v2.0/config-guide/memcache/memcache_centos.html