返回

PHP-FPM性能调优:解决服务器瓶颈

Linux

PHP-FPM 性能调优

当服务器上的 PHP 应用遇到性能瓶颈,导致响应时间变长或者 CPU、内存资源占用率过高时,往往需要对 PHP-FPM (FastCGI Process Manager) 进行调优。 PHP-FPM 作为 PHP 解释器进程的管理工具,其配置参数会直接影响到应用性能。不合理的参数配置可能导致资源浪费、请求处理延迟,甚至导致服务不稳定。本文将分析可能出现的问题,并提供相应的调优方案。

常见问题

  1. FPM 进程频繁创建与销毁:
    PHP-FPM 日志中出现 seems busy...spawning... 以及 server reached pm.max_children 警告信息,表明当前 FPM 进程数量不足以处理突增的请求。服务器尝试不断创建新进程,当达到 pm.max_children 限制后,新的请求会被阻塞。进程的频繁创建销毁本身也会消耗系统资源,并降低响应速度。 这种现象可能表明需要调整 pm.max_childrenpm.start_serverspm.min_spare_serverspm.max_spare_servers 等参数。

  2. FPM 进程无故终止: 日志中出现 Terminating...exiting, bye-bye! 的提示表示 FPM 进程在执行过程中遇到了问题并被迫停止,可能是由于进程内存溢出或请求超时。如果频繁出现这类提示,需要检查代码中是否存在资源泄漏,或者增加FPM的超时时间设置。

  3. 内存占用高: 通过 psfree -hl 命令观察到 php-fpm 进程占用大量内存,而且可用内存较低,说明当前的 PHP-FPM 设置可能并未完全合理。 如果内存不足会引发 swap 占用过高,也会降低性能,这时就需要进一步分析具体是哪些 php-fpm 子进程消耗了内存,需要考虑调整 pm.max_requests 并关注应用程序代码本身的内存使用情况。

解决方案

以下给出几个调优方向,可以依据自身服务器情况和应用特点进行选择和调整。

方案一:合理设置进程数量

PHP-FPM 使用 pm 参数决定进程管理方式。 通常,选择 dynamic模式相对平衡资源消耗和请求处理效率。需要调整的核心参数有以下几个:

  • pm.max_children: 设置同时运行的 FPM 子进程的最大数量。该参数是避免系统资源被过度使用的重要因素,应结合服务器内存大小和应用所需内存进行设置。过高的值可能会导致内存溢出,过低的值会导致请求被阻塞。经验上,建议计算每个进程平均内存消耗,以及可用内存资源总量。推荐的算法是 pm.max_children = 内存 / (平均每个PHP-FPM进程占用内存) 。可以通过反复测试找到最佳的值。
  • pm.start_servers: 设置 FPM 启动时创建的子进程数量。 如果过低可能导致访问量增大时 FPM 创建进程缓慢从而响应延迟, 如果设置过高则可能会消耗内存资源。 一般将其设置为 (CPU核数 X 2)或 (CPU核数 X 3) ,或者等于 pm.min_spare_servers
  • pm.min_spare_servers: 设置 FPM 保持空闲的最小子进程数量。目的是保证有一定量的进程等待新的请求。推荐的值为 (CPU核数) 或 (CPU核数 X 2)
  • pm.max_spare_servers: 设置 FPM 保持空闲的最大子进程数量。超出此值会终止闲置的进程以回收资源。一般等于 (CPU核数 X 3)或(CPU核数 X 4).

操作步骤:

  1. 找到 PHP-FPM 配置文件,通常位于 /etc/php/版本号/fpm/pool.d/www.conf 或类似位置。

  2. 修改相应的 pm.* 参数,可以使用如下建议的值,假设CPU核数是8:

    pm = dynamic
    pm.max_children = 64  ; 需要根据实际情况调整
    pm.start_servers = 16 ; (8 x 2) 
    pm.min_spare_servers = 8 ; (8 x 1)
    pm.max_spare_servers = 24; (8 x 3) 
    
  3. 重启 PHP-FPM 服务,使配置生效:

    sudo systemctl restart php<版本号>-fpm
    

    注意替换 <版本号> 为实际安装的 PHP 版本。

方案二:限制进程请求次数

频繁创建、销毁进程的另一个原因可能是某个或某些请求造成内存泄漏,或者 FPM 子进程处理过多请求后出现内存泄露的情况,pm.max_requests 可以帮助我们避免长时间运行的子进程。此配置参数规定了每个子进程在退出重启之前可以处理的请求次数。通过设置 pm.max_requests, 可以定期回收内存资源,并预防内存泄露造成的问题。

操作步骤:

  1. www.conf 中,加入以下参数:
 pm.max_requests = 1000
 ```

  设置合适的值,一般来说, `1000-5000` 是常见的取值。

2.  保存文件,重启 php-fpm。
```bash
sudo systemctl restart php<版本号>-fpm

方案三: 监控和调整

通过修改配置并非最终方案。持续监控PHP-FPM状态,调整配置以匹配实际服务器资源使用情况也是必需的。 例如,在业务高峰期,需要考虑增加 FPM 的资源配置;在业务低谷期,则可以适当减少。推荐使用类似 Prometheus 配合 Grafana 来监控,或者用 systemctl 查看进程的 CPU、内存使用状况。
同时需要定期检查PHP-FPM 的错误日志, 及时发现问题,例如是否有php执行超时,或者内存泄露等问题。

附加安全建议

  • 避免在 www.conf 直接使用过大的 pm.max_children , 防止 PHP 出现问题的时候耗尽服务器资源。 可以使用脚本和告警系统,动态的设置 pm.max_children 等参数。

  • pm.status_path 参数可以提供FPM状态页, 可以监控FPM的请求队列和空闲状态,但切记做好访问权限控制,避免泄露敏感信息。

  • 保持PHP和相关扩展库的版本在最新状态,及时修补安全漏洞,从而避免入侵风险。

以上建议仅供参考,服务器配置应该依据实际的业务场景和资源状况进行调整。务必在每次更改配置之后观察效果,及时回滚配置或再次进行调整。 理解各个参数的作用,并依据实际情况做出合理的配置,对于维护服务器的稳定性和应用的高性能至关重要。