在上一篇文章中,我们探讨了 PHP 在服务器端的基本流程:用户访问 .php
文件,PHP 在服务器上执行该脚本,然后将 HTML 返回给浏览器。
但是,一旦你的项目超越了"能正常工作"的阶段,性能就开始变得重要。可靠性开始变得重要。流量模式、内存使用、超时——这些都变成了现实问题。
这时你需要了解 PHP 实际上是如何运行的,而不仅仅是如何编写它。
🧭 为什么理解这些真的很重要
大多数 PHP 应用程序开箱即用。但这并不意味着它们已经准备好投入生产。
如果你不了解 PHP 在服务器上是如何执行的,你最终会面临:
了解 PHP 的运行机制可以让你构建出:
让我们来看看如何实现这些目标。
🧬 PHP 是无状态的——那为什么它如此快速?
每次 PHP 处理请求时,它都从零开始。用户之间没有内存共享,没有长时间运行的进程,没有像 Node.js 或 Java 那样的内存缓存。
那么 PHP 是如何每秒处理数千个请求的呢?
答案是:
这两个系统使 PHP 在生产环境中变得可行。
⚡ OPcache:编译脚本,存储在内存中
默认情况下,PHP 在每个请求上都会读取、解析和编译脚本。
这意味着即使你的代码没有改变,PHP 仍然会执行:
请求 → 磁盘读取 → 解析 → 编译 → 执行 → 响应
OPcache 通过将脚本的编译版本存储在共享内存中来改变这一点。
✅ 为什么你必须使用它
🛠 如何配置 OPcache
在 php.ini
中:
opcache.enable=1
opcache.memory_consumption=192
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; 用于生产环境
部署后重启 PHP-FPM,以便 OPcache 重新加载最新代码。
❌ 常见错误:在生产环境中保留 validate_timestamps=1
— PHP 会持续检查文件系统,你会失去 OPcache 的大部分好处。
🔁 PHP-FPM:管理 PHP 如何处理多个请求
PHP-FPM 是 FastCGI 进程管理器——它控制 PHP 如何处理并发流量。
PHP-FPM 不是为每个请求生成新的 PHP 进程(很慢),而是维护一个持久 PHP 工作进程池,准备处理传入的请求。
🧠 实际发生的过程:
这让你可以处理数百或数千个用户,而无需每次都启动新的 PHP 进程。
🔧 如何调优 PHP-FPM(实际示例)
编辑 /etc/php/8.2/fpm/pool.d/www.conf
:
pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 4
pm.max_spare_servers = 12
pm.max_requests = 1000
request_terminate_timeout = 30
🧮 如何计算 pm.max_children:
ps -o rss,cmd -C php-fpm | awk '{ sum+=$1 } END { print sum/NR/1024 " MB" }'
示例:
🔐 使用超时保护你的工作进程
长时间运行的脚本(如慢速数据库查询或 API 调用)可能会冻结 PHP-FPM 工作进程。如果太多进程冻结,整个网站就会变慢或崩溃。
设置超时和请求限制:
request_terminate_timeout = 30
pm.max_requests = 1000
这些确保:
📂 Realpath 缓存:加速自动加载
PHP 在使用 include
、require
或自动加载器(如 Composer)时会不断解析文件路径。
你可以缓存这些路径来减少文件系统调用:
在 php.ini
中:
realpath_cache_size = 4096k
realpath_cache_ttl = 600
这对于 Laravel、Symfony 或任何有大型 vendor 目录的应用来说都是巨大的胜利。
🔍 使用 /status 监控一切
在 PHP-FPM 中启用 /status
:
在 www.conf
中:
pm.status_path = /status
在你的 Web 服务器中:
location /status {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
include fastcgi_params;
allow 127.0.0.1;
deny all;
}
然后:
curl http://localhost/status
关注:
🐌 使用慢日志调试慢脚本
在 www.conf
中:
request_slowlog_timeout = 5
slowlog = /var/log/php/slow.log
这会记录任何运行时间超过 5 秒的请求的回溯信息。
这对于调试真实世界的缓慢问题非常有用——特别是在负载下。
🚀 额外功能:预加载(可选,高级)
你可以在任何请求到达服务器之前将 PHP 文件预加载到内存中(PHP 7.4+)。
在 php.ini
中:
opcache.preload=/var/www/myapp/preload.php
opcache.preload_user=www-data
在 preload.php
中:
require_once __DIR__.'/vendor/autoload.php';
require_once __DIR__.'/app/CoreKernel.php';
这避免了自动加载开销,非常适合大型应用。
🧠 最后的想法:从代码到执行
作为一名 PHP 开发者,了解 PHP 的执行机制是一种超能力。
你不需要成为系统管理员。但如果你:
...那么你的 PHP 应用将更快、更稳定,在生产环境中更容易管理。
✅ 技术总结
性能不是魔法。它是配置。
稳定性不是运气。它是测量。
扩展不是重写。它是理解你的运行时如何工作。