冷启动与热启动指标
解读
在国内 PHP 面试中,面试官问“冷启动与热启动指标”通常不是让你背操作系统定义,而是考察你对 PHP 生命周期、SAPI 差异、Opcache 命中率、容器化弹性伸缩以及高并发场景下真实耗时表现的理解。
“冷启动”指 PHP 进程从无到有:fpm 子进程刚 fork、Opcache 为空、框架尚未加载、连接池未建立、容器镜像刚拉取。
“热启动”指进程已常驻:fpm 子进程复用、Opcache 已预热、框架类已载入、连接池长连、容器已缓存。
面试官想看你能不能量化这两种状态对 RT(Response Time)、P99、CPU、内存、QPS 的影响,并给出线上可落地的监控与优化方案。
知识点
- PHP 生命周期:SAPI 层 → MINIT → RINIT → 执行脚本 → RSHUTDOWN → MSHUTDOWN;CLI 与 php-fpm 差异。
- Opcache 原理:共享内存缓存 opcode,interned string,wasted memory 重组,restart 策略(OOM/手动/时间)。
- fpm 进程模型:static、dynamic、ondemand;max_children、pm.start_servers、pm.max_spare_servers 对冷启动并发毛刺的影响。
- 容器冷启动:镜像体积、composer autoload 文件数、OPcache 预加载脚本、read-only 层、kubelet 并行拉取、istio sidecar 注入。
- 指标口径:
- 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。
- 预热手段:preload.php(PHP 7.4+)、laravel/octane、swoole/table、连接池预建、opcache-gui 压测脚本、Kubernetes postStart hook。
- 监控体系:Prometheus + Grafana:php-fpm_exporter、opcache_exporter、kubelet 指标;日志链路:OpenTelemetry + Jaeger,冷启动 span 自动打 tag:cold_start=true。
答案
冷启动指标:
- 请求 RT 的 P99 比热启动高 3~10 倍,例如热启动 30 ms,冷启动 150 ms;
- Opcache 命中率从 0% 爬升到 98% 需要 2000 次请求或 5 s 压测;
- fpm 新建子进程耗时 5~8 ms,若并发 1000 QPS 突发,ondemand 模式下可能瞬间 fork 200 进程,导致 CPU steal 飙升 30%;
- 容器镜像 600 MB、composer autoload 文件 8000 个时,kube 冷启动拉取+解压 25 s,使用 dragonfly p2p 后可降到 6 s;
- 内存占用:冷启动首个请求常驻内存 38 MB,热启动稳定 22 MB,差异来自框架容器、连接池、注解缓存未共享。
热启动指标:
- RT P99 稳定 ≤ 50 ms(业务 99 线);
- Opcache 命中率 ≥ 99%,wasted memory ≤ 10%,restart 次数 0;
- fpm 进程池 idle 占比 20%~40%,无频繁 kill/max 告警;
- 长连接复用率:MySQL > 90%,Redis > 95%,无 connect 重建;
- 容器存活 7×24 h,无 OOMKilled,cgroup CPU throttle 率 < 5%。
优化落地:
- 上线前使用 opcache-preload 把 200+ 核心类固化到共享内存,冷启动 RT 降 40%;
- fpm 采用 static 模式,start_servers = max_children = 核数 × 2,提前分配,杜绝突发 fork;
- 容器化场景把 composer vendor 提前编译到镜像,autoload 使用 authoritative 模式,减少 60% stat 调用;
- 灰度发布配合 Kubernetes readinessProbe,预热脚本请求 100 次后再接流量,保证流量切进来时已是热启动;
- 监控看板设置 SLO:冷启动样本占比 < 1%,否则触发 on-call,自动回滚或扩容。
拓展思考
- Serverless PHP(B 函数计算、阿里云 FC)冷启动可达 800 ms,如何利用 custom runtime + snapshot 技术把冷启动降到 100 ms 以内?
- 当 Opcache 最大内存设置 256 MB 仍出现 5% wasted,如何编写 CLI 脚本在凌晨低峰期做 smart restart 而不掉流量?
- 使用 Laravel Octane + Swoole 时,worker 热重载导致“热启动”重新载入 2000 个类,如何区分“进程热”与“类热”,并给出新的指标口径?
- 多机房流量调度场景,冷启动样本可能集中在某个新机房,如何基于 traceId 做实时染色,让网关把冷启动请求导流到低峰节点,实现“冷流量隔离”?