本文目录导读:

- 明确监控维度(大盘要展示什么)
- 技术选型推荐
- PHP 埋点实现(重点)
- 避免埋点耦合业务代码(高阶技巧)
- 部署 Prometheus 与 Grafana
- PHP 监控必踩的 3 个坑(注意事项)
- 更轻量:如果不想用 Prometheus
在 PHP 项目中搭建业务监控大盘,核心思路是埋点采集 → 存储聚合 → 可视化展示,由于 PHP 通常是无状态、请求驱动的,推荐采用 Prometheus + Grafana 或 ELK/ClickHouse + Grafana 架构。
以下是 PHP 业务监控大盘的完整落地指南,分为指标类型、技术选型、埋点实现、大盘设计四个部分。
明确监控维度(大盘要展示什么)
在写代码前,先定义你要监控的业务指标,通常分为三类:
| 维度 | 核心指标(Metrics) | 示例(电商场景) |
|---|---|---|
| 流量 | QPS、PV/UV、请求耗时(P50/P95/P99) | 今日订单量、平均响应时间 |
| 业务 | 订单量、GMV、转化率、退款笔数、注册人数 | 实时销售额、支付成功率 |
| 资源 | 队列堆积量(Redis/Kafka)、MySQL慢查询、CPU/内存 | 待支付订单超时数量、库存扣减失败数 |
技术选型推荐
轻量级方案(推荐):Prometheus + Grafana
- 优点:PHP只需要暴露一个
/metrics端点,不需要引入重量级SDK;Grafana自带丰富的图表模板。 - 数据流:
业务代码(Counter/Gauge)→Prometheus(拉取)→Grafana(曲线/仪表盘)。
中大型方案:ClickHouse / InfluxDB + Grafana
- 适合海量日志级别的业务事件(如用户点击流),适合做明细分析。
注意:不建议用 MySQL 做实时监控聚合,写入太频繁且查询慢。
PHP 埋点实现(重点)
使用 prometheus/client_php 库(官方推荐)来实现。
安装扩展(Composer)
composer require promphp/prometheus_client_php
初始化 Registry(单例)
use Prometheus\CollectorRegistry; use Prometheus\Storage\APCng; // 使用 APC或Redis 存储,避免每次请求都写文件 $registry = CollectorRegistry::getDefault(); $registry->setStorage(new APCng());
定义关键 3 个指标类型
① Counter(计数器):累计值,只增不减,用于订单量/总GMV
$counter = $registry->getOrRegisterCounter('app', 'orders_total', '总订单数', ['channel']);
// 业务触发点:下单成功后
$counter->incBy(1, ['wechat']); // 微信渠道 +1
$counter->incBy(250.5, ['alipay']); // 支付宝渠道的 GMV 累加
② Gauge(仪表盘):可增可减,用于库存/在线人数
$gauge = $registry->getOrRegisterGauge('app', 'stock_remaining', '剩余库存');
// 扣库存时
$gauge->dec(1);
// 补库存时
$gauge->inc(10);
// 也可以直接设定为某个值
$gauge->set(99);
③ Histogram(直方图):记录请求耗时分布,用于计算 P99
$histogram = $registry->getOrRegisterHistogram('app', 'request_duration_seconds', '接口耗时', ['route'], [0.1, 0.5, 1, 2, 5]);
// 在请求结束时
$histogram->observe($elapsed_time); // 手动计算耗时
暴露 /metrics 端点(供 Prometheus 拉取)
// metrics.php 或者路由响应
use Prometheus\RenderTextFormat;
// 业务埋点执行完后,输出文本格式
$renderer = new RenderTextFormat();
$result = $renderer->render($registry);
header('Content-Type: text/plain; charset=utf-8');
echo $result;
注意:必须在
ob_start()之前输出,且不要加exit()否则可能截断。
避免埋点耦合业务代码(高阶技巧)
为了代码整洁,建议用 AOP(切面)或中间件 处理公共指标,业务代码只留关键业务事件。
示例:用中间件统计耗时和 QPS
class MetricsMiddleware {
public function handle($request, Closure $next) {
$start = microtime(true);
// 业务执行
$response = $next($request);
$duration = microtime(true) - $start;
// 记录耗时
$histogram->observe($duration, [$request->getPath()]);
// 记录当前在线(可以是Redis里的活跃key数量)
$gauge->set(redis()->zcard('active_users'));
return $response;
}
}
部署 Prometheus 与 Grafana
Prometheus 配置(prometheus.yml)
scrape_configs:
- job_name: 'php_app'
static_configs:
- targets: ['web1:8080/metrics', 'web2:8080/metrics'] # 多实例
metrics_path: '/metrics'
scrape_interval: 15s
Grafana 可视化面板设计(核心)
新建 Dashboard,添加以下 Panel(面板):
| 面板名称 | PromQL 表达式(查询语言) | 图类型 |
|---|---|---|
| 实时 QPS | sum(rate(app_orders_total[$__rate_interval])) by (channel) |
折线图 |
| GMV 趋势 | sum(increase(app_orders_total[1h])) by (channel) |
面积图 |
| 接口慢查询排行 | histogram_quantile(0.95, sum(rate(app_request_duration_seconds_bucket[5m])) by (le, route)) |
热力图 |
| 库存预警 | app_stock_remaining < 10 (阈值告警) |
统计图/状态灯 |
| 业务转化漏斗 | 直接使用 SQL 数据源(如 ClickHouse)做漏斗,或直接用 app_payment_success_count / app_order_count |
仪表盘/Gauge |
PHP 监控必踩的 3 个坑(注意事项)
-
多进程问题:PHP-FPM 是多进程的,指标默认存储在内存(APC)中,每个 worker 的数据是独立的,导致数据分散。解决:必须使用
Redis或Memcached存储适配器,集中统一存储指标。use Prometheus\Storage\Redis; $registry = new CollectorRegistry(new Redis(['host' => '127.0.0.1']));
-
服务重启数据丢失:Prometheus 是拉取制,PHP 进程重启,内存中的计数器会清零,导致曲线断崖式下跌。解决:若要跨重启持久化,指标存 Redis;但如果不需要历史累计,仅看变化率(rate)则问题不大。
-
性能损耗:不要高频调用
inc(),建议通过 异步队列 或 定时批量写入 来批量上报,避免每笔请求都写 Redis。
更轻量:如果不想用 Prometheus
如果项目很小,可以直接用 Redis 计数器 + Grafana 的 Redis 数据源,实现一个简易大盘。
步骤:
- PHP 每次下单执行:
redis->incr('order_count_today')。 - 在 Grafana 直接配置 Redis 数据源,查询该 key 的实时值。
- 缺点:无法做复杂的聚合对比,只能做基础数值展示。
如果你想快速上线一个专业级的 PHP 业务大盘,请记住这个组合PHP-FPM + Redis存储指标 + Prometheus拉取 + Grafana可视化**。
核心步骤回顾:
- 用
prometheus/client_php注册 Counter/Gauge/Histogram。 - 在订单、支付等关键业务逻辑触发时
inc记录。 - 使用 Redis 存储数据避免多进程分叉。
- 在
/metrics端点展示 Prometheus 格式文本。 - 配置 Prometheus 抓取 + Grafana 画图。
这样即可实现“实时 QPS 曲线 + 业务曝光/点击/支付漏斗 + P99 延迟告警”的专业大盘。