首页 > 代码库 > 高性能PHP应用开发-总结

高性能PHP应用开发-总结

最近将《高性能PHP应用开发》这本书看了两遍,觉得还是受益匪浅的,该书讲的面比较广,都是经验性的内容,建议大家有时间可以详细看一下的,基于此特意将本书的精华易用的部分加以整理,子曰:“温故而知新,可以为师矣。”

 

 


[第一章  基准测试工具]

一:Apache Benchmark (ab) 

随 apache包一起安装
ab -n (请求数) -c (并发数,不能起过-n) -t (请求的秒数) http://url

报告中最重要的是以下字段内容:
-------------------------
HTML transferred  请求的内容总大小 
Requests per second 每秒最多支持的并发数请求数
Time per request 一个请求需要的总时间
Time per request 所有总发请求中的一个请求时间
-------------------------

二:Siege [可以指定URL列表文件]
安装:
wget ftp://ftp.joedog.org/pub/siege/siege-latest.tar.gz 
tar xvfz siege-latest.tar.gz 
cd siege-2.69/ 
./configure 
make && install

siege -c (并发数) -t(时间数)([S(秒)/M(分)/H(小时)]) [URL] -i -f (URL列表文件)

报告中最重要的是以下字段内容:
-------------------------
Data transferred 响应中数据的总大小(不包括标记头数据)
Transaction rate 每秒要满足的事务总数
Longest transaction 满足一个请求所需的最长时间
Shortest transaction 满足一个请求所需的最短时间
[其它说明]
Transactions 已完成的事务总数
Availability 能够请求WEB文档的时间
Elapsed Time 完成测试所需的总时间
Response time 整个测试过程中的平均响应时间
Throughput 处理数据和响应所需的总时间
Concurrency 同时连接的平均数,该数字升高时服务器性能降低
Successful transactions 整个测试过程中执行成功的事务总数
Failed transactions 整个测试过程中执行成功的失败总数
-------------------------


[第二章  提高客户端下载和呈现性能]

一:工具集:
firebug / YSlow / Page Speed  - YUI Compressor / Closure Compiler / Smush.it

Firebug Net选项卡颜色的含义
-------------------------------------
紫色 浏览器正在等待资源
灰色 正在接收资源
红色 正在发送
绿色 正在连接
蓝色 DNS查找
-------------------------------------

二:YSlow V2 规则集

(一):CSS优化
1:将样式CSS文件放在顶部
2:避免CSS表达式
3:压缩CSS文件

(二):图像优化规则
1:使用所要要求的图像大小,而不是用样式来调整大小
2:可能的情况下创建画面,即将所有的小图标都放在一个大图中,采用订位方式呈现

(三):javascript优化规则
1:将JS文件放在层部
2:将JS代码做成外部文件
3:压缩JS文件大小

(四):服务器优化
1:采用CDN
2:采用 Gzip/bzip2 压缩
3:减少DNS的查找
4:实现 Etag

YSlow 评分是从 A=>D (高到底)

三:图片使用通用规则:

使用GIF做页面上徽标和小图标,用JPEG呈现照片,其它一切图片使用PNG格式。
图片可以使用 YSlow->Tools->Smush.it


[第三章  PHP代码优化]


1:使用 require 比 require_once 快(stat调用次数少)
require_once() 在导入脚本时要进行大量的操作状态调用,如果文件位于
/data/web/html/php/a.php 则每个目录都要进行一次stat的调用。

2:提示计算循环的次数

3:尽可能的使用 foreach 方便数据,它的速度最快.

4:文件读取原则:
小文件(<1M)使用: fread() 快点
大文件(>=1M)使用: file_get_contents() 快点


[第四章  Opcode缓存]

1:Alternative PHP Cache (APC)

安装源:http://downloads.php.net/pierre/

(APC常用设置)
-----------------------------------------
apc.cache_by_default 默认启用缓存.1:启用 0:禁用
apc.filters 采用正则表达式来判断是要缓存的文件
apc.stat 是否启用对请求脚本的更新检查,每次调用脚本时都会执行这个过程,
1:启用 0:禁用,如果有对PHP脚本更改的话则要重启WEB服务器
apc.enabled 是否启用缓存 1:启用 0:禁用
apc.shm_size 设置共享内存的大小,以M为单位
apc.shm_segments 可用的共享内存段总数
apc.include_once_override 是否启用对include_once和require_once的优化,
启用时可以减少stat的调用. 1:启用 0:禁用
apc.optimization 优化级别,0:禁用该功能,设置为较高数值可以提高优化级别 1-9
apc.num_files_hint 设置你认为要缓存的文件数,默认是1000,如果不确定则设置为0,
设置为实际数可以提高性能.
apc.ttl 设置缓存的过期时间,只有到达过期时间时才会从缓存中清除,单位:秒
apc.write_lock 开启该选项时将强制单个进程缓存特定的脚本,适用于必须缓存多
个文件的大流量WEB应用.
-----------------------------------------
(APC配置示例)
extension=apc.so 
apc.enabled=on 
apc.shm_size=16 
apc.include_once_override=1 
apc.write_lock=1 
apc.optimization=9 
apc.stat=0 
apc.num_files_hint=5 

(APC管理工具)
安装包中自带了 apc.php 这个网页工具,放到Web服务目录下就可以运行了.


2:XCache

安装源: http://xcache.lighttpd.net
[XCache]
Zend_extension_ts=php_xcache.dll  (ts:表示线程安全)

(XCache常用设置)
-----------------------------------------
xcache.admin.user (string)认证用户名
xcache.admin.pass (string)认证密码
xcache.admin.enable_auth (string)是否启用认证,默认: ‘on‘
xcache.test (string)是否启用测试功能
xcache.coredump_dir (string)故障时放置核心转储的目录,该目录必需PHP有写权限,
保留为空时代表禁用
xcache.cacher (Boolean) 是否启用缓存,默认启用
xcache.size (int) 共享缓存大小,如果为0则缓存将无法使用
xcache.count (int)缓存被分配的"块"数,默认为1
xcache.slots 哈希表提示,数字越大,哈希表内进行的搜索速度就越快,此值越大,
所需要的内存也越多
xcache.ttl (int) Opcode文件的生存时间,如果为0则无限期缓存
xcache.gc_interval (int)触发垃圾回收的时间间隔,默认为0
xcache.var_size (int)变量大小
xcache.var_count (int)变量个数
xcache.var_slots 可变数据槽设置
xcache.var_ttl (秒)可变数据的生存时间,默认为0
xcache.var_maxttl (秒)处理变量时最大的生存时间
xcache.var_gc_interval (秒)垃圾回收的生存时间
xcache.readonly_protection (Boolean)启用时会减慢工具的运行速度,但更加安全.
xcache.mmap_path  (String) 用户只读保护的文件路径.这将限制两个PHP组共享同一个 /tmp/cache 目录
xcache.optimizer  (Boolean) 是否启用优化,默认:关闭
xcache.coverager  (Boolean) 启用覆盖范围数据集合,启用后会减慢运行过程
xcaceh.coveragedump_directory (String) 放置数据集合信息的目录,默认:/tmp/pcovis
-----------------------------------------

3:eAccelerator (可以将缓存存在磁盘上)

安装源: http://www.eaccelerator.net
wget http://bart.eaccelerator.net/source/0.9.6.1/eaccelerator-0.9.6.1.tar.bz2  
tar xvjf eaccelerator-0.9.6.1.tar.bz2 
phpize 
./configure 
make && make install

(缓存数据的方法)
eaccelerator.keys = [shm_and_disk:默认值,如果内存空间不足就存入磁盘 shm_only:只使用内存 
disk_only:只使用硬盘]

默认的存放目录:/tmp/eaccelerator 在每次系统重启时会清空,建议更改为以下目录
mkdir -p /var/cache/eaccelerator
chmod 0777 -R /var/cache/eaccelerator

(eA配置项说明)
----------------------------------------------------
eaccelerator.shm_size
共享内存大小,单位: MB. “0″代表操作系统默认。默认值为 “0″。

eaccelerator.cache_dir
磁盘缓存的目录。默认值为 “/tmp/eaccelerator”

eaccelerator.enable
开启或关闭 eAccelerator。”1″ 为开启,”0″ 为关闭。默认值为 “1″。

eaccelerator.optimizer
开启或关闭内部优化器,可以提升代码执行速度。”1″ 为开启,”0″ 为关闭。默认值为 “1″。

eaccelerator.debug
是否启用调试日志,日志记录在eaccelerator.log_file中 。”1″ 为开启,”0″ 为关闭。默认值为 “0″。

eaccelerator.log_file
目录文件,没有指定时所有的日志在 stderr 中,如果使用 apache则在apache的日志中

eaccelerator.name_sapce
一个所有键(keys)的前缀字符串。如果设置该前缀字符串则允许 .htaccess 或者主配置文件在相同主机上运行两个相同的键名。

eaccelerator.check_mtime
开启或关闭 PHP 文件改动检查。”1″ 为开启,”0″ 为关闭。如果您想要在修改后重新编译 PHP 程序则需要设置为 “1″。默认值为 “1″。

eaccelerator.filter
判断哪些 PHP 文件必须缓存。您可以指定缓存和不缓存的文件类型(如 “*.php *.phtml”等)。如果参数以 “!” 开头,则匹配这些参数的文件被忽略缓存。默认值为 “”所有 PHP 文件都将被缓存。

eaccelerator.shm_max
当使用 ” eaccelerator_put() ” 函数时禁止其向共享内存中存储过大的文件。该参数指定允许存储的最大值,单位: 字节 (10240,10K,1M)。”0″ 为不限制。默认值为 “0″。

eaccelerator.shm_ttl
当 eAccelerator 获取新脚本的共享内存大小失败时,它将从共享内存中删除所有在最后 “shm_ttl” 秒内无法存取的脚本缓存。默认值为 “0″,即: 不从共享内春中删除任何缓存文件。

eaccelerator.shm_prune_period
当 eAccelerator 获取新脚本的共享内存大小失败时,他将试图从共享内存中删除早于 “shm_prune_period” 秒的缓存脚本。默认值为 “0″,即: 不从共享内春中删除任何缓存文件。

eaccelerator.shm_only
允许或禁止将已编译脚本缓存在磁盘上。该选项对 session 数据和内容缓存无效。默认值为 “0″,即: 使用磁盘和共享内存进行缓存。

eaccelerator.compress
允许或禁止压缩内容缓存。默认值为 “1″,即: 允许压缩.

eaccelerator.compress_level
指定内容缓存的压缩等级。默认值为 “9″,为最高等级.

eaccelerator.keys
eaccelerator.sessions
eaccelerator.content
判断哪些键(keys),session 数据和内容将被缓存。
可用参数值为: 
“shm_and_disk” – 同时在共享内存和磁盘中缓存数据(默认值); 
“shm” – 如果共享内存用尽或者数据容量大于 “eaccelerator.shm_max”,则在共享内存或磁盘中缓存数据; 
“shm_only” – 仅在共享内存中缓存数据; 
“disk_only” – 仅在磁盘中缓存数据; 
“none” – 禁止缓存数据。

eaccelerator.admin.name 用户名
eaccelerator.admin.password 密码
eaccelerator.allowed_admin_path 该脚本路径允许获得管理信息并进行管理控制.
----------------------------------------------------

(eA配置示例)
extension="eaccelerator.so" 
eaccelerator.shm_size="16" 
eaccelerator.cache_dir="/var/cache/eaccelerator" 
eaccelerator.enable="1" 
eaccelerator.optimizer="1" 
eaccelerator.check_mtime="1" 
eaccelerator.debug="0" 
eaccelerator.filter="" 
eaccelerator.shm_max="0" 
eaccelerator.shm_ttl="0" 
eaccelerator.shm_prune_period="0" 
eaccelerator.shm_only="0" 
eaccelerator.compress="1" 
eaccelerator.compress_level="9" 


[第五章  变量缓存]
Apc/ Memcache 安装源: http://www.memcached.org


[第六章  选择正确的Web报务器]

一:综合要考虑的问题

1:安全性和稳定性非常重要
apache是当前最安全和稳定的服务程序包.

2:找到具有丰富知识和经验的工程师非常重要
如果你想找到一流的Web服务技术工程师,Apaceh是最佳选择

3:你的网站是否主要是静态内容
如果绝大部分是静态内容,推荐使用 Nginx/Lighttpd

4:你在托管服务中托管
如果你是在托管服务中,在采用依赖非Apaceh时,要查询一下托管服务没是否支持的.

5;你正在使用不常见的PHP扩展
大多数PHP扩展在开发时是在带有 mod_php 模块的apaceh上开发,Nginx/Lighttpd 使用的
FCGI模式下通常没有做过严格的测试,在选择这些WEB服务前一定检查是否能在 FCGI模式下运行正常.

二:Web服务器的分类

(Prefork/Fork)
基于进程的Web服务器,使用fock进程来满足每个请求;推荐单CPU或数据库集成/文件处理的
应用程序使用这种类型,因为第三方的扩展中大部分未证明是线程安全的.

(Threaded)
基于线程的Web服务器,使用线程来满足每个请求;

三:Apache HTTPD

命令行参数 httpd -h
-----------------------------------------
-D name 设置名称以便在<ifDefine name>指令中使用
-d directory 设置 ServerRoot
-f file 设置ServerConfigFile
-C "directive" 在读取配置文件之前对指令进行处理
-c 在读取配置文件之后对指令进行处理
-e level 显示日志级别为"level"的启动错误
-E file 将启动错误记录记录到‘file‘文件中
-V 显示编译设置
-l 列出已编译的模块
-L 列出可用的配置指令
-t -D DUMP_VHOSTS 显示所有的Vhost设置
-S (-t -D DUMP_VHOSTS 的快捷方式)
-t -D DUMP_MODULES 显示已加载的模块
-M (-t -D DUMP_MODULES 的快捷方式)
-t 检查配置文件语法
-----------------------------------------

Apache中可用的MPM(多处理模块)列表
-------------------------------------------
Prefork: 预告创建一组子进程.(默认安装方式)
Perchild: Prefork的一个变体,它允许为子进程设置单独的进程权限
Threadpool: 使用多线程来实现对请求的处理-大多数Unix类系统不建议使用,原来是无法保证线程安全.
Worker: Prefork和Threadpool的混合,其中每个子进程都支持多个线程.
-------------------------------------------
建议使用 Prefork MPM,任何多线程的MPM都是不推荐的,因为多很绑定到Apache和PHP解释器的库文件
都未证明的是线程安全的.

(安装其它Web服务时结合Fast-Cgi模式的PHP配置)
#[FastCGI PHP]
cgi.fix_pathinfo = 1 (修复以前CGI实现中的一个BUG)


[第七章  优化Web服务器和内容交付]

1:测定 Web服务器的性能

ApacheTop 安装
--------------------------------------------------------------
wget http://www.webta.org/apachetop/apachetop-0.12.6.tar.gz 
sudo yum install readline-devel 
sudo yum install ncurses-devel 
sudo yum install pcre-devel 
tar xvzf apachetop-0.12.6.tar.gz 
cd apachetop-0.12.6 
./configure 
make 
sudo make install 
--------------------------------------------------------------

使用: apachetop -f /var/log/apache2/access_log 参数说明如下:
-----------------------------------------------------------
-f:logfile打开被监控的日志文件
-H hits:窗口显示最新的hits条访问记录.例:-H 10
-T sec:窗口显示的url访问记录清空时间间隔,默认30秒..
-d secs:窗口显示的数据刷新时间,默认5秒刷新一次.例:-d 2
示例:apachetop -f /usr/local/nginx/logs/access_log -T 500 -d 2


介面参数详细说明如下:
----------------------------------------------
第一行:分别是上次点击时的时间、apachetop运行总时间、现在的时间
第二,四行:表示的是请求数、平均每秒请求数、平均每秒传输量、平均每请求传输量; 
不同的是,第二行是从apachetop开始运行计算的,第四行是从上一次清空请求时开始计算的,
在行首的括号里的时间,这个时间和下面提到的-T和-d 参数是有关系的,-T是多少,这个时间最大就是多少,
-d是多少,这个时间就一次增加几,直到和-T的时间相等,就不变了。

过滤机制操作如下:
----------------------------------------------
依次键入:"f""a""u",然后转入:".php",则过滤以.php结尾的URL

2:优化 Apache Prefork MPM
vi /etc/apache2/conf/extra/httpd-mpm.conf
---------------------------------------------------
指令                         说明                     
---------------------------------------------------
StartServers 控制Aapache启动时将生成的客户端数,由于创建客户端有开销,最好是拥有足够的客户端来处理空闲的流量.(默认值:5)
MinSpareServers 正常情况下,如果请求数减少并且Apache无法提供拥有这些请求的正常理由,则Apache会终止一些客户端.该指令对Apaceh
将保持活动的客户端数设置了一个较低的限制,它不应低于 StartServers(默认值:5)
MaxSpareServers 该指令设置Apache开始放弃客户端的点.如果活动客户端数比当前正在处理的并发请求数多10个以上,那么Apache将开始
终止和放弃客户端,直到这个数量达到MinSpareServers值,该址设置得太低,会导致Apache封杀客户端进程,因些小心使用此设置.(默认值:10)
MaxClients 该指令设置Apache将产生的最大进程数,从而设置它可以处理的最大同时并发请求数.(默认值:150)
MaxRequestsPerChild 该指令设置子进程在被终止和重新产生之前将处理的最大请求数.如果设置为0,则该进程是永久存在的,永远不会死亡.(默认值:0)

3:优化内存使用和防止产生交换
一般经验1G的内存最多可以支持65个并发请求.这里可以更改MaxClients为65便不会过渡的使用内存.
为了确保在负载上运行时不被封杀客户端,大概应该将StartServers为了65的一半30左右.同时也将
MinSpareServers设置为30,再将MaxSpareServers设置为40,这是适当值可以防止封杀客户端.

4:Aapche其它优化
a:尽可能是的禁用 .htaccess 文件, AllowOverride禁用
b:禁用 FollowSymlinks
c:DirectoryIndex 第一个文件应该指定使用最频繁的文件
d:关闭HostnameLookup的DNS查找
e:启用 Keep-Alive 的永久连接
f:使用 mod_deflate 来压缩内容

5:负载均衡(将请求分发到多台服务器)
a:使用 Round-Robin DNS
b:使用负载均衡器,软件一般有:LVS,mod_proxy 硬件:F5,CoyotePoint,Cisco,Juniper等.
c:负载均衡服务,Amazon Elastic Load Balancer等.

6:多服务器之间共享会话
a:Memcache
b:共享目录文件(NFS等)
c:数据库

7:服务器部署
多米诺骨牌失败效应:假定一个由两台服务器组成的服务器群,基于负载平均值和并发等,每台服务器的负载大概为其
容量的60%,这两台服务器中的一台服务器发生故障会导致另一台试图去处理总能力的120%的负载,从而引发它也会产生失败.

所以设计一个服务器群集时必需要确保它可以容忍一个或多个服务器发生故障.如果只有两台服务器,则必需监控其负载因子,
如果负载起过50%,则应该计划添加额外的服务器了.否则容易进入多米诺骨牌失败效应.

多台服务器部署时,可以考虑为每台服务器设置一个内部的DNS域名为验证,如 www1.demo.com,www2.demo.com 等.


[第八章  数据库优化-MySql]
------------------------------------
MyISAM优点:
1:可以快速查询唯一值
2:支持全文搜索
3:选择Count(*)的速度很快
4:磁盘空间占用少
------------------------------------
MyISAM缺点:
1:表级别锁,如果程序的写入操作点总时间的5%以上,则表锁会减慢程序的速度
2:不支持事务的能力
3:有持久性问题,表崩溃需要冗长的修复操作才可以恢复
----------------------------------

------------------------------------
InnoDB优点:
1:支持事务能力
2:具有行级的锁定功能,并发写入同一表时不会被序列化
3:支持多种联机备份策略.
4:提高了程序在高负载,高并发下的能力.
------------------------------------
InnoDB缺点:
1:选择count(*)很慢,它需要计算行.
2:没有全文搜索.
3:自增字段必需是第一字段,在迁移时可能会导致问题.
4:点用更多的磁盘空间.
5:简单的查表速度不如MyISAM,但复杂的,多个表的查询速度则起过了MyISAM.
----------------------------------

选择引擎的总结:
1:程序执行的大部分时间是读操作(95%以上)则应该选择MyISAM.
2:当事务性和一致性非常重要时,应该选择InnoDB.
3:当你有一个包含很多连接表的复杂模式时.应该选择InnoDB.
4:当不间断操作非常重要时,如果全天24*7的运行,建议选择InnoDB.

(Mysql内存使用比较)

每个连接(线程)使用的内存数量:
per_connection_memory = 
read_buffer_size                               // memory for sequential table scans 
+read_rnd_buffer_size                          // Memory for buffering reads 
+sort_buffer_size                              // Memory for in mem sorts 
+thread_stack                                  // Per connection memory 
+join_buffer_size                              // Memory for in mem table joins 

每服务器(固定)使用的内存数据:
per_server_memory = 
tmp_table_size                                 // memory for all temp tables 
+max_heap_table_size                           // max size of single temp table 
+key_buffer_size                               // memory allocated for index blocks 
+innodb_buffer_pool_size                       // main cache for InnoDB data 
+innodb_additional_mem_pool_size               // InnoDB record structure cache 
+innodb_log_buffer_size                        // log file write buffer 
+query_cache_size                              // compiled statement cache 

MySql可以使用的最大的内存定义如下:
max_memory = (per_connection_memory * max_connections) + per_server_memory


优化数据库服务器的内存工具: Mysqltuner.pl

1:安装
wget mysqltuner.pl -O mysqltuner.pl
chmod +x mysqltuner.pl
./mysqltuner.pl

(优化 InnoDB)
以下假设基于16G的内存:
innodb_file_per_table:
默认情况下,innodb为每个数据库创建一个文件并用这个文件来管理数据表.这意味着如果表的大小先增大然后又缩小,
则很难恢复磁盘空间.设置了该值将使每个表使用一个独立的数据存储文件.如果想在现在的数据库上更改此设置,应该
备份该数据库,然后删除它,再更改选项,然后新新启动服务后从备份中恢复数据.
innodb_buffer_pool_size=:
如果只使用Innodb表,可以设置为可用内存的70%左右,如果混合使用了MyISAM,则要减小一点给MyISAM空间.
innodb_log_buffer_size=4M:
4M可以满足绝大部分记录的需求,面具提供合理的性能.如果拥有很大的文本字段或blob字段,或者记录非常大的,可以设高点.
innodb_log_file_size=256M
这是推荐的值,可以在恢复数据库的速度与操持较高的运行时性能之间取得良好的平衡.
innodb_flush_log_at_trx_commit=2
这一项控制日志文件刷新到磁盘的频率.如果可以容忍在发生崩溃时丢失一些记录,那么可以把它设为2来减少磁盘的写入.
可选择项: 0:每秒同步写入 1:及时写入 2:写入缓存,由操作系统控制写入

(记录慢查询)
[mysqld]
log-slow-queries=/var/log/mysql/mysqld-slow.log
long_query_time=1

(分析有问题的查询)
explain 工具

(PHP数据库应用程序的建议)
1:一开始就考虑使用 M/S 的读写方案,为以后的升级增加方便.
2:默认使用utf8的字符集,
3:使用UTC日期格式
3.1:安装时区数据库
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
[mysqld]
default-time-zone=UTC