PHP-FPM进程如何热重启worker进程?

PHP-FPM 不能“点名重启某一个子进程”,但可以用信号、pm 策略和 reload 机制,让子进程被安全回收并重建


1. PHP-FPM 进程模型

1.1 角色划分

  • Master 进程

    • 读取配置
    • 监听 socket/端口
    • 管理 Worker(子进程)
  • Worker / Child 进程

    • 实际执行 PHP 请求
    • 按 pm 策略自动增减
    • 崩溃后由 Master 拉起

1.2 master-worker关系示意

graph TD
    M[php-fpm master]
    C1[worker 1]
    C2[worker 2]
    C3[worker N]

    M --> C1
    M --> C2
    M --> C3

关键点:所有“重启子进程”的动作,本质都是 Master 在做调度


2. 如何优雅重启worker进程

2.1 平滑重载(最推荐)

1
kill -USR2 <php-fpm-master-pid>

效果

  • Master 重新加载配置
  • 旧子进程:处理完当前请求后退出
  • 新子进程:逐步拉起
  • 对线上请求影响最小(几乎无感)

👉 这是 生产环境首选


2.2 使用 systemctl reload

1
systemctl reload php-fpm

等价于 USR2,更规范。


3. 只重启子进程的实际可行方案

3.1 杀掉 Worker,让 Master 自动重建

不建议

3.1.1 找到 Worker PID

1
ps -ef | grep php-fpm | grep pool

示例输出:

www      12345  1000  php-fpm: pool www
www      12346  1000  php-fpm: pool www

3.1.2 kill 某个子进程

1
kill -TERM 12345

结果

  • 这个 worker 退出
  • Master 立刻拉起一个新的 worker
  • 其他 worker 不受影响

这是最接近“重启指定子进程”的方式


3.2 快速回收全部子进程(不中断 Master)

1
kill -WINCH <master-pid>

效果

  • 所有 worker 优雅退出
  • Master 仍在
  • 随后根据 pm 策略重新 fork

⚠️ 短时间并发能力会下降,不适合流量高峰。


4. 信号速查表

信号 作用 是否推荐
USR2 平滑 reload(重建子进程) ⭐⭐⭐⭐⭐
TERM 杀某个 worker ⭐⭐⭐⭐
WINCH 停掉全部 worker ⭐⭐
QUIT 优雅关闭整个 FPM ⚠️
KILL 强杀 ❌ 生产禁用

5. 通过 pm 策略“自动重启异常子进程”(根治方案)

5.1 推荐配置(生产)

1
2
3
4
5
6
7
8
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20

; 防内存泄漏神器
pm.max_requests = 1000

5.2 原理

  • 每个 worker 执行 1000 次请求后 自动退出

  • Master 自动拉起新 worker

  • 无需人工干预

  • 非常适合:

    • 内存泄漏
    • 扩展不稳定
    • 第三方 SDK 有问题

6. 不推荐但你可能见过的“野路子”

6.1 重启 php-fpm 服务

1
systemctl restart php-fpm

❌ 问题:

  • 所有请求中断
  • socket 断开
  • 对 Nginx 不友好

只适合 配置错误 / FPM 卡死


7. 生产级操作建议

7.1 正确操作顺序

  1. 单 worker 异常

    • kill -TERM <worker-pid>
  2. 批量内存上涨(解决内存泄露问题)

    • 调低 pm.max_requests
  3. 配置调整

    • systemctl reload php-fpm
  4. 整体异常

    • 才考虑 restart