FrankenPHP 无内置内存异常告警,须依赖 Prometheus + process-exporter 监控 process_resident_memory_bytes(RSS)实现 OOM 前预警;memory_limit 仅为 PHP 脚本软限制,不防系统级 OOM,因其不控制 C 扩展、opcache 共享内存及 mmap 等 RSS 组成部分。

FrankenPHP 本身不提供内存异常告警能力,必须靠外部监控系统捕获进程 RSS 内存并触发告警。 它没有内置的 memory_get_usage() 阈值回调、也没有类似 --memory=512M 的 CLI 自动退出机制。告警这件事,得交给 Prometheus + process-exporter 这类工具来干。
为什么不能只靠 PHP 的 memory_limit?
PHP 的 memory_limit 是脚本级软限制:超限会抛出 Fatal error: Allowed memory size exhausted,但进程不会被杀,也不会上报指标。OOM Killer 真正动手时,看的是进程的 RSS(常驻集大小),而 RSS 可能远高于 memory_limit(比如大量未释放的 C 扩展内存、opcache 共享内存、或 mmap 分配)。所以仅设 memory_limit = 256M 对防 OOM 杀手毫无意义。
-
memory_limit防的是 PHP 脚本逻辑性内存滥用,不是系统级内存耗尽 - FrankenPHP worker 模式下,框架和连接长期驻留,RSS 会缓慢爬升,
memory_limit根本不触发 - 容器内存限制(如
mem_limit: 512m)生效时,内核已准备调用 OOM Killer,此时再告警就晚了
怎么用 process-exporter + Prometheus 告警 RSS?
process-exporter 能采集 FrankenPHP 主进程的 process_resident_memory_bytes,这是最贴近 OOM 风险的真实指标。
- 确保 FrankenPHP 进程名可识别:启动时加
--name=frankenphp-web(Caddy 启动 FrankenPHP 时默认进程名是caddy,建议显式重命名) - 在 process-exporter 配置中匹配该名称:
process_names: [{ cmdline: ".*frankenphp-web.*", name: "frankenphp" }] - Prometheus 抓取后,写告警规则:
process_resident_memory_bytes{job="process-exporter",name="frankenphp"} > 450 * 1024 * 1024(假设容器上限 512MB) - Alertmanager 触发时,可执行
curl -X POST http://localhost:2019/healthz?graceful-shutdown(需提前配置 FrankenPHP 的健康端点支持优雅退出)
worker 模式下哪些内存行为容易被忽略?
FrankenPHP 的 worker 模式让应用常驻,但也放大了内存管理盲区:
立即学习“PHP免费学习笔记(深入)”;
- 数据库连接池不会自动回收闲置连接,
PDO::ATTR_PERSISTENT开启后,每个 worker 的连接会一直占着内存 - 全局静态变量(如
static $cache = [])在 worker 生命周期内持续累积,unset()不一定立即释放 RSS - Opcache 的
opcache.memory_consumption是共享内存,不计入单个 FrankenPHP 进程 RSS,但会影响整体容器内存水位 - 日志 handler(如 Monolog 的
RotatingFileHandler)若未设置max_files,可能因句柄泄漏拖垮 RSS
真正关键的不是“设多少 MB”,而是盯住 process_resident_memory_bytes 这个值在真实流量下的变化曲线——它才是 FrankenPHP 是否快被 OOM Killer 点名的唯一可信信号。



















