各位观众老爷们,大家好!我是你们的老朋友,专门和代码打交道的。今天咱们来聊聊PHP-FPM的调优,让你的网站跑得飞起,不再被用户吐槽“卡成PPT”。
PHP-FPM,全称FastCGI Process Manager,是PHP的一个进程管理器,负责接收Web服务器(如Nginx或Apache)的请求,然后执行PHP代码,最后把结果返回给Web服务器。简单来说,它就是个辛勤的搬运工,把PHP代码变成用户能看到的页面。
但是,如果这个搬运工太懒或者太笨,你的网站就会变得很慢。所以,我们需要对PHP-FPM进行调优,让它更勤快、更聪明。
咱们今天就从进程管理、请求处理和配置优化三个方面入手,一步一步地把PHP-FPM调教成一匹真正的千里马。
一、进程管理:让搬运工的数量和质量都上去
PHP-FPM的进程管理主要涉及到以下几个参数:
pm
:进程管理方式,有static
、dynamic
和ondemand
三种。pm.max_children
:最大子进程数,决定了PHP-FPM最多能同时处理多少个请求。pm.start_servers
:启动时创建的子进程数,相当于预热,让PHP-FPM一开始就有足够的劳动力。pm.min_spare_servers
:空闲时保持的最小子进程数,保证随时都有人干活。pm.max_spare_servers
:空闲时保持的最大子进程数,避免浪费资源。pm.max_requests
:每个子进程处理多少个请求后重启,防止内存泄漏。
1.1 选择合适的进程管理方式
-
static
: 静态模式,启动时创建固定数量的子进程,以后不再增减。- 优点: 简单粗暴,省去了动态创建和销毁进程的开销。
- 缺点: 如果请求量少,会浪费资源;如果请求量大,可能会导致请求堆积。
- 适用场景: 资源充足,并且请求量相对稳定的情况。
pm = static pm.max_children = 50
-
dynamic
: 动态模式,根据请求量动态创建和销毁子进程。- 优点: 能够根据请求量自动调整资源,更加灵活。
- 缺点: 创建和销毁进程会带来一定的开销。
- 适用场景: 请求量波动较大的情况。
pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20
-
ondemand
: 按需模式,只有在有请求时才创建子进程。- 优点: 资源利用率最高,只有在真正需要的时候才会占用资源。
- 缺点: 每次请求都需要创建进程,开销最大。
- 适用场景: 资源非常有限,并且请求量非常小的情况。
pm = ondemand pm.max_children = 50 pm.process_idle_timeout = 10s; // 子进程空闲多久后销毁 pm.max_requests = 500
选择建议: 如果你的服务器资源充足,并且请求量相对稳定,可以选择
static
模式;如果请求量波动较大,可以选择dynamic
模式;如果资源非常有限,可以选择ondemand
模式。
1.2 设置合理的进程数量
pm.max_children
是影响性能的关键参数。设置得太小,会导致请求堆积;设置得太大,会导致内存耗尽。
如何确定pm.max_children
的值?
一种常用的方法是根据服务器的内存来计算。假设你的服务器有8GB内存,每个PHP进程平均占用50MB内存,那么pm.max_children
可以设置为:
pm.max_children = 8GB / 50MB = 160
但这只是一个参考值,你需要根据实际情况进行调整。你可以通过监控PHP-FPM的运行状态,观察CPU和内存的使用情况,来确定最佳的pm.max_children
值。
监控PHP-FPM的运行状态:
你可以通过php-fpm status page
来监控PHP-FPM的运行状态。首先,你需要配置Nginx或Apache,允许访问php-fpm status page
:
Nginx配置:
location /php-fpm-status {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING status;
fastcgi_param SCRIPT_NAME /php-fpm-status;
include fastcgi_params;
}
Apache配置:
<Location /php-fpm-status>
<IfModule mod_authz_core.c>
Require ip 127.0.0.1
</IfModule>
SetHandler php-fpm-status
</Location>
然后,你需要修改PHP-FPM的配置文件,开启php-fpm status page
:
pm.status_path = /php-fpm-status
重启Nginx/Apache和PHP-FPM后,你就可以通过访问http://your_domain/php-fpm-status
来查看PHP-FPM的运行状态了。
监控指标:
active processes
:当前活跃的进程数。idle processes
:当前空闲的进程数。accepted connections
:已接受的连接数。listen queue
:等待处理的连接数。max children reached
:达到最大子进程数的次数。
如果listen queue
的值很高,或者max children reached
的值经常增加,说明你的pm.max_children
设置得太小了,需要适当增加。
1.3 重启进程的策略
pm.max_requests
参数决定了每个子进程处理多少个请求后重启。重启进程可以释放内存,防止内存泄漏。
设置建议: 可以根据你的应用情况设置pm.max_requests
的值。如果你的应用经常出现内存泄漏,可以设置得小一点;如果你的应用比较稳定,可以设置得大一点。一般可以设置为500
到1000
之间。
二、请求处理:让搬运工跑得更快
PHP-FPM的请求处理主要涉及到以下几个方面:
- Opcode缓存: 避免重复编译PHP代码。
- 数据库连接池: 减少数据库连接的开销。
- 静态资源缓存: 减少对磁盘的访问。
2.1 开启Opcode缓存
Opcode是PHP代码编译后的中间代码。开启Opcode缓存后,PHP-FPM会将Opcode缓存起来,下次执行相同的PHP代码时,直接使用缓存的Opcode,避免重复编译。
常用的Opcode缓存扩展:
- OPcache: PHP官方推荐的Opcode缓存扩展,性能优秀,配置简单。
- APC: 曾经非常流行的Opcode缓存扩展,但现在已经停止维护,不建议使用。
开启OPcache:
首先,你需要安装OPcache扩展:
sudo apt-get install php-opcache # Debian/Ubuntu
sudo yum install php-opcache # CentOS/RHEL
然后,你需要修改PHP的配置文件php.ini
,开启OPcache:
zend_extension=opcache.so
opcache.enable=1
opcache.memory_consumption=128 ; 单位MB
opcache.interned_strings_buffer=8 ; 单位MB
opcache.max_accelerated_files=4000
opcache.validate_timestamps=0 ; 生产环境建议关闭
opcache.revalidate_freq=0 ; 生产环境建议设置为0
opcache.enable_cli=1
参数说明:
opcache.enable
:是否开启OPcache。opcache.memory_consumption
:OPcache使用的内存大小。opcache.interned_strings_buffer
:OPcache缓存字符串的内存大小。opcache.max_accelerated_files
:OPcache最多缓存的文件数。opcache.validate_timestamps
:是否检查文件的时间戳。在开发环境中,建议开启;在生产环境中,建议关闭,以提高性能。opcache.revalidate_freq
:检查文件时间戳的频率。在开发环境中,建议设置为1
或2
;在生产环境中,建议设置为0
。opcache.enable_cli
:是否在命令行模式下开启OPcache。
重启PHP-FPM后,OPcache就开始工作了。你可以通过phpinfo()
函数来查看OPcache的运行状态。
2.2 使用数据库连接池
每次连接数据库都需要建立TCP连接,这个过程比较耗时。使用数据库连接池可以减少数据库连接的开销,提高性能。
常用的PHP数据库连接池:
- PDO: PHP Data Objects,PHP官方提供的数据库访问接口,支持多种数据库。
- mysqli: MySQL Improved Extension,MySQL官方提供的PHP扩展,性能优秀。
- Medoo: 一个轻量级的PHP数据库框架,支持多种数据库,使用简单。
使用PDO连接池:
<?php
class Database {
private static $pdo;
public static function getConnection() {
if (!isset(self::$pdo)) {
$dsn = 'mysql:host=localhost;dbname=your_database';
$username = 'your_username';
$password = 'your_password';
$options = [
PDO::ATTR_PERSISTENT => true, // 开启持久连接
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
];
try {
self::$pdo = new PDO($dsn, $username, $password, $options);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
return self::$pdo;
}
}
// 使用示例
$pdo = Database::getConnection();
$stmt = $pdo->prepare("SELECT * FROM users");
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
说明:
PDO::ATTR_PERSISTENT => true
:开启持久连接,让PHP-FPM在多个请求之间重用数据库连接。PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
:设置错误处理模式为异常模式,方便调试。
2.3 缓存静态资源
静态资源(如图片、CSS文件、JavaScript文件等)不需要PHP-FPM处理,可以直接由Web服务器返回。将静态资源缓存起来,可以减少对磁盘的访问,提高性能。
常用的静态资源缓存方式:
- 浏览器缓存: 通过设置HTTP Header,让浏览器缓存静态资源。
- CDN: Content Delivery Network,将静态资源分发到全球各地的服务器,让用户可以就近访问。
设置HTTP Header:
<?php
// 设置缓存时间为1小时
header('Cache-Control: max-age=3600');
// 设置过期时间为1小时后
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
?>
三、配置优化:让搬运工更省力
PHP-FPM的配置优化主要涉及到以下几个方面:
- 错误日志: 记录错误信息,方便调试。
- 慢日志: 记录执行时间超过阈值的请求,方便排查性能问题。
- 请求超时: 设置请求超时时间,防止恶意请求占用资源。
3.1 开启错误日志
错误日志可以帮助你快速定位问题。建议开启错误日志,并设置合适的日志级别。
配置示例:
error_log = /var/log/php-fpm.log
log_level = warning ; 可选值:error, warning, notice, debug
参数说明:
error_log
:错误日志文件的路径。log_level
:日志级别。error
级别只记录错误信息,warning
级别记录错误和警告信息,notice
级别记录错误、警告和通知信息,debug
级别记录所有信息。
3.2 开启慢日志
慢日志可以帮助你找到执行时间过长的请求,从而排查性能问题。
配置示例:
request_slowlog_timeout = 3s ; 请求执行时间超过3秒,就记录到慢日志
slowlog = /var/log/php-fpm.slow.log
参数说明:
request_slowlog_timeout
:请求执行时间超过多少秒,就记录到慢日志。slowlog
:慢日志文件的路径。
3.3 设置请求超时
请求超时可以防止恶意请求占用资源。建议设置合理的请求超时时间。
配置示例:
request_terminate_timeout = 60s ; 请求执行时间超过60秒,就强制终止
参数说明:
request_terminate_timeout
:请求执行时间超过多少秒,就强制终止。
四、总结
PHP-FPM的调优是一个持续的过程,需要根据实际情况进行调整。希望今天的讲座能帮助你更好地理解PHP-FPM,并能调教出更优秀的PHP-FPM,让你的网站跑得更快、更稳。
记住,没有一劳永逸的配置,只有不断优化才能让你的网站保持最佳状态。 各位,下次再见!