ThinkPHP 项目响应缓慢,最常见的原因是 PHP 的 OPcache 扩展未启用或配置不当,导致每次请求都重复编译脚本。
先说结论:生产环境务必开启 OPcache 并调整内存与文件数限制,这是提升 TP5 执行效率最直接的手段。
- 先定位:通过 phpinfo() 确认 Web 环境是否真实加载了 OPcache 扩展。
- 先做:在 Web 对应的 php.ini 中启用扩展并调整 memory_consumption 与 max_accelerated_files 参数。
- 再验证:重启服务后调用 opcache_get_status() 确认缓存命中率与状态。
命令速用版
若你有服务器命令行权限,可先快速检查扩展状态与配置文件路径:
php -m | grep opcache php `--ini`
若第一行有输出且第二行显示了配置文件路径,说明 CLI 环境下已加载,但 Web 环境(如 PHP-FPM)可能使用了不同的配置文件,需进一步通过网页验证。
为什么会这样
PHP 是解释型语言,默认情况下每次请求都需要重新读取源码、编译成字节码(Opcode)再执行。OPcache 的作用是将编译后的字节码缓存到共享内存中,后续请求直接复用,避免了重复的解析与编译开销。对于 ThinkPHP 这类包含大量框架文件与 vendor 依赖的项目,开启 OPcache 能显著降低 CPU 负载与请求延迟。
分步处理
1. 确认 Web 环境的配置文件路径
在 ThinkPHP 项目的 public 目录下新建 info.php 文件,内容为:<?php phpinfo(); ?>。通过浏览器访问该文件,搜索"Loaded Configuration File",记录其指向的 php.ini 绝对路径。若页面中搜索"Opcode Caching"显示为 Disabled 或无此区块,说明扩展未在当前 Web 环境加载。
2. 启用 OPcache 扩展
使用文本编辑器打开上一步确认的 php.ini 文件。查找;zend_extension=opcache.so(Linux)或;zend_extension=php_opcache.dll(Windows),删除行首的分号取消注释。确保使用的是 zend_extension 指令而非 extension,否则加载失败。
3. 调整关键参数
在 [OpCache] 段落或文件末尾添加以下配置,根据项目规模调整数值:
opcache.enable=1 opcache.memory_consumption=256 opcache.max_accelerated_files=20000 opcache.validate_timestamps=1 opcache.revalidate_freq=60 opcache.fast_shutdown=1
其中 memory_consumption 建议设为 256(单位 MB),max_accelerated_files 建议设为 20000 以防缓存溢出。注意:生产环境若使用容器或 rsync 部署,validate_timestamps 可设为 0 但需在发布后手动清除缓存,否则代码更新不会生效。
4. 重启服务
修改配置后必须重启 Web 服务或 PHP-FPM 才能生效。例如:sudo systemctl restart php-fpm 或 sudo systemctl restart apache2。
怎么验证是否生效
刷新之前的 info.php 页面,确认"Opcode Caching"状态为 Enabled。此外,可在任意 PHP 脚本中运行:
<?php $status = opcache_get_status(); var_dump($status ? $status['opcache_enabled'] : false); ?>
若返回 true 且 memory_usage 中的 used_memory 随请求增长,说明缓存正在工作。
常见坑
1. CLI 与 Web 配置不一致
命令行 php -m 显示有 opcache 不代表网页能用,两者可能读取不同的 php.ini,务必以 phpinfo() 显示的路径为准。
2. 代码更新不生效
若 validate_timestamps 设为 0,OPcache 不会检查文件修改时间。更新代码后需手动调用 opcache_reset() 或重启服务,否则页面仍显示旧内容。
3. 内存不足导致缓存失效
若 max_accelerated_files 设置过小或 memory_consumption 不足,缓存会频繁重置。可通过 opcache_get_status() 监控 missed_cache 与 num_cached_scripts 指标。
附:一键清除缓存脚本
若配置了 validate_timestamps=0,部署后可通过以下脚本手动清除缓存。建议在 public 目录下创建 clear_cache.php,使用后及时删除:
<?php
if (function_exists('opcache_reset')) {
opcache_reset();
echo 'OPcache cleared successfully.';
} else {
echo 'OPcache extension not loaded.';
}
?>