冷启动与热启动指标

解读

在国内 PHP 面试中,面试官问“冷启动与热启动指标”通常不是让你背操作系统定义,而是考察你对 PHP 生命周期、SAPI 差异、Opcache 命中率、容器化弹性伸缩以及高并发场景下真实耗时表现的理解。
“冷启动”指 PHP 进程从无到有:fpm 子进程刚 fork、Opcache 为空、框架尚未加载、连接池未建立、容器镜像刚拉取。
“热启动”指进程已常驻:fpm 子进程复用、Opcache 已预热、框架类已载入、连接池长连、容器已缓存。
面试官想看你能不能量化这两种状态对 RT(Response Time)、P99、CPU、内存、QPS 的影响,并给出线上可落地的监控与优化方案。

知识点

  1. PHP 生命周期:SAPI 层 → MINIT → RINIT → 执行脚本 → RSHUTDOWN → MSHUTDOWN;CLI 与 php-fpm 差异。
  2. Opcache 原理:共享内存缓存 opcode,interned string,wasted memory 重组,restart 策略(OOM/手动/时间)。
  3. fpm 进程模型:static、dynamic、ondemand;max_children、pm.start_servers、pm.max_spare_servers 对冷启动并发毛刺的影响。
  4. 容器冷启动:镜像体积、composer autoload 文件数、OPcache 预加载脚本、read-only 层、kubelet 并行拉取、istio sidecar 注入。
  5. 指标口径:
    • RT 分布:P50、P99、P999;冷启动样本需标记 traceId 并采样。
    • Opcache 命中率 = (hits / (hits + misses)) * 100%,低于 98% 视为异常。
    • fpm 进程池利用率 = (active_processes / max_children) * 100%,持续高于 80% 需扩容。
    • 容器启动耗时 = pod create → pull image → start container → probe ready,目标 ≤ 3 s。
  6. 预热手段:preload.php(PHP 7.4+)、laravel/octane、swoole/table、连接池预建、opcache-gui 压测脚本、Kubernetes postStart hook。
  7. 监控体系:Prometheus + Grafana:php-fpm_exporter、opcache_exporter、kubelet 指标;日志链路:OpenTelemetry + Jaeger,冷启动 span 自动打 tag:cold_start=true。

答案

冷启动指标:

  1. 请求 RT 的 P99 比热启动高 3~10 倍,例如热启动 30 ms,冷启动 150 ms;
  2. Opcache 命中率从 0% 爬升到 98% 需要 2000 次请求或 5 s 压测;
  3. fpm 新建子进程耗时 5~8 ms,若并发 1000 QPS 突发,ondemand 模式下可能瞬间 fork 200 进程,导致 CPU steal 飙升 30%;
  4. 容器镜像 600 MB、composer autoload 文件 8000 个时,kube 冷启动拉取+解压 25 s,使用 dragonfly p2p 后可降到 6 s;
  5. 内存占用:冷启动首个请求常驻内存 38 MB,热启动稳定 22 MB,差异来自框架容器、连接池、注解缓存未共享。

热启动指标:

  1. RT P99 稳定 ≤ 50 ms(业务 99 线);
  2. Opcache 命中率 ≥ 99%,wasted memory ≤ 10%,restart 次数 0;
  3. fpm 进程池 idle 占比 20%~40%,无频繁 kill/max 告警;
  4. 长连接复用率:MySQL > 90%,Redis > 95%,无 connect 重建;
  5. 容器存活 7×24 h,无 OOMKilled,cgroup CPU throttle 率 < 5%。

优化落地:

  1. 上线前使用 opcache-preload 把 200+ 核心类固化到共享内存,冷启动 RT 降 40%;
  2. fpm 采用 static 模式,start_servers = max_children = 核数 × 2,提前分配,杜绝突发 fork;
  3. 容器化场景把 composer vendor 提前编译到镜像,autoload 使用 authoritative 模式,减少 60% stat 调用;
  4. 灰度发布配合 Kubernetes readinessProbe,预热脚本请求 100 次后再接流量,保证流量切进来时已是热启动;
  5. 监控看板设置 SLO:冷启动样本占比 < 1%,否则触发 on-call,自动回滚或扩容。

拓展思考

  1. Serverless PHP(B 函数计算、阿里云 FC)冷启动可达 800 ms,如何利用 custom runtime + snapshot 技术把冷启动降到 100 ms 以内?
  2. 当 Opcache 最大内存设置 256 MB 仍出现 5% wasted,如何编写 CLI 脚本在凌晨低峰期做 smart restart 而不掉流量?
  3. 使用 Laravel Octane + Swoole 时,worker 热重载导致“热启动”重新载入 2000 个类,如何区分“进程热”与“类热”,并给出新的指标口径?
  4. 多机房流量调度场景,冷启动样本可能集中在某个新机房,如何基于 traceId 做实时染色,让网关把冷启动请求导流到低峰节点,实现“冷流量隔离”?