php-prometheus-exporter 不是标准 composer 包,需手动集成并启动独立进程才能暴露指标;它依赖 prometheus/client_php 但不包含其功能,二者须共享同一 collectorregistry 实例(通过文件或 apcu),且 exporter 进程必须单独运行监听指定端口。

直接说结论:PHP-Prometheus-Exporter 不是标准 Composer 包,不能通过 composer require 一键安装;它本质是一个轻量级 HTTP 服务包装器,需手动集成 + 启动独立进程,否则指标根本不会暴露。
为什么 composer require prometheus/client_php 不等于导出指标
很多人误以为装了官方客户端 prometheus/client_php 就能“导出”——其实它只负责在内存里收集和序列化指标(Prometheus\CollectorRegistry),不提供 HTTP 端点。而 PHP-Prometheus-Exporter 是另一个项目(GitHub 上的 php-pm/php-prometheus-exporter 或社区 fork),作用是监听请求、调用客户端的 $registry->getMetricFamilySamples() 并返回文本格式数据。
常见错误现象:
- 安装了 prometheus/client_php,但访问 /metrics 返回 404 或空响应
- 指标写入了 registry,Prometheus 抓取时返回 204 或空内容
- 本地 curl http://localhost:9090/metrics 失败,提示连接被拒绝
- 必须单独运行 exporter 进程(不是 PHP-FPM 或 Laravel artisan 命令)
-
prometheus/client_php和 exporter 进程必须共享同一个CollectorRegistry实例 —— 通常靠文件或 APCu 共享,不能每次请求新建 - exporter 默认监听
127.0.0.1:9090,若部署在容器中,需绑定0.0.0.0:9090并开放端口
如何正确启动 PHP-Prometheus-Exporter 进程
目前最稳定可用的是 php-pm/php-prometheus-exporter(注意不是 prometheus/client_php 的子包)。它依赖 ReactPHP,需用命令行启动:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
php vendor/bin/prometheus-exporter --host=0.0.0.0 --port=9090 --registry-file=/tmp/prom-registry.php
关键参数说明:
- --registry-file:指定一个可读写的临时文件路径,exporter 会从这里反序列化 registry 数据(客户端需用 serialize() 写入)
- --host 和 --port:决定监听地址,K8s Service 或 Prometheus scrape config 必须匹配此地址
- 它不支持热重载,修改代码后需 kill 进程再重启
- 确保
/tmp/prom-registry.php所在目录 Web 进程和 exporter 进程都有读写权限 - 不要用
nohup直接后台运行,建议配合 systemd 或 supervisor 管理进程生命周期 - 如果用 Docker,需在
Dockerfile中 expose 端口,并在启动命令中显式设置--host=0.0.0.0
PHP 应用中如何向 registry 写入并持久化指标
你的业务代码(如 Laravel 中间件、Swoole onRequest 回调)要复用同一个 registry,并定期 dump 到文件:
$registry = \Prometheus\CollectorRegistry::getDefault();
$counter = $registry->getOrRegisterCounter('app', 'http_requests_total', ['method', 'code']);
$counter->inc(['GET', '200']);
<p>// 必须写入文件,供 exporter 进程读取
file_put_contents('/tmp/prom-registry.php', serialize($registry));</p>
注意点:
- 频繁 serialize() + file_put_contents() 有 I/O 开销,建议每秒最多 1–2 次,或用 apcu_store() + export 进程读 APCu(需启用 --use-apcu 参数)
- 若用 Swoole 或 RoadRunner,registry 可驻留在常驻内存中,无需每次请求重建
- 不要用 $_SESSION 或 Redis 存 registry —— exporter 无法直接访问,且序列化兼容性差
- 避免在 CLI 命令中写指标后立即 dump,因为 exporter 进程可能刚读完旧文件,新内容还没刷到磁盘
- 测试时先用
php -r "var_dump(unserialize(file_get_contents('/tmp/prom-registry.php')));"确认文件可反序列化 - 若出现
unserialize(): Error at offset,大概率是并发写入导致文件损坏,加flock()锁
真正麻烦的不是写几行代码,而是 registry 共享机制的选择和稳定性验证——文件锁、APCu 生效范围、进程间内存隔离,这些细节一旦出问题,Prometheus 就收不到任何数据,还查不出错在哪。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










