worker崩溃典型现象是日志中反复出现workererror回调或“worker_id=2 exited, code=255, signal=0”;第一判断线索为该输出或请求超时、连接堆积、内存持续上涨。

Worker崩溃的典型现象和第一判断线索
看到日志里反复出现 WorkerError 回调被触发,或者 worker_id=2 exited, code=255, signal=0 这类输出,基本能确认是 Worker 进程非正常退出。更隐蔽的是进程没报错但请求开始超时、连接堆积、内存持续上涨——这往往是未捕获异常或内存泄漏导致的“慢性崩溃”,比直接段错误更难定位。
致命错误(E_ERROR/E_PARSE)怎么捕获不到?
PHP 的致命错误不会抛出 Exception,try-catch 完全无效,必须靠 register_shutdown_function + error_get_last() 组合兜底。但要注意:这个函数只在当前 Worker 进程内生效,必须在 WorkerStart 里注册,而不是全局写一次。
- 漏掉
workerstart回调里的注册,整个 Worker 就失去兜底能力 -
error_get_last()返回null时别硬解析,要先判空 - 记录日志时务必带上
$workerId和时间戳,否则多进程日志混在一起根本分不清谁挂了
为什么 max_request 设成 0 反而更容易崩?
设为 0 表示永不重启 Worker,等于把内存泄漏、资源句柄累积、静态变量污染等所有问题都堆在一个进程里。实际生产中,max_request 是最廉价的“防崩保险丝”。它不解决根本问题,但能阻止单个 Worker 恶化到 segfault 或 OOM。
- 常规值建议 1000–5000,高内存消耗服务(如图片处理)可压到 500 以下
- 搭配
max_request_grace使用,避免请求中途被砍断 - 如果发现 Worker 总是在接近
max_request时退出,说明不是配置问题,而是真有泄漏——该查代码了
段错误(SIGSEGV)和信号退出怎么快速区分?
WorkerError 回调里的 $signal 值是关键:11 是 SIGSEGV(段错误),9 是 SIGKILL(大概率被 OOM Killer 干掉),15 是 SIGTERM(人为 kill 或 systemd 停止)。别光看 exit_code,信号值才是真相。
- 查
dmesg -T | grep -i "killed process"确认是否 OOM - 段错误必须开 core dump:
ulimit -c unlimited+echo "/tmp/core.%e.%p" > /proc/sys/kernel/core_pattern - 用
gdb php core.xxx查栈帧,重点看 extension 调用或 C 扩展传参是否越界








