加载中…
文档目录
性能指标收集

简介

本文件为 DouPHP 构建“性能指标收集系统”的实施方案与实现说明,覆盖以下目标:

  • 响应时间监控:API 接口响应时间、页面加载时间的统计方法。
  • 吞吐量统计:QPS 监控、并发请求数统计、处理队列长度监控。
  • 错误率监控:异常捕获、错误分类、错误趋势分析。
  • 自定义指标:支持业务特定指标采集。
  • 存储策略:选择时序数据库进行指标数据存储。
  • 可视化方案:使用 Grafana 等工具展示监控数据。

本项目已具备日志基础设施与限流中间件,可作为指标采集的基础设施与触发点;同时存在按日聚合的统计能力(如聊天用量/日统计),可借鉴其模式扩展至通用性能指标。

项目结构

围绕性能指标收集,建议采用“采集—汇聚—存储—可视化”的分层设计:

  • 采集层:在 HTTP 边界(中间件)和关键业务入口埋点,记录耗时、状态码、错误、资源占用等。
  • 汇聚层:将高频指标以采样/批处理方式写入本地日志或消息通道,降低对主流程影响。
  • 存储层:通过导出器/Agent 将指标写入时序数据库(如 Prometheus/TimescaleDB/OpenTelemetry)。
  • 可视化层:Grafana 对接时序库,提供仪表盘与告警。
graph TB
A["HTTP 请求"] --> B["中间件<br/>ThrottleMiddleware / 安全头"]
B --> C["路由与控制器"]
C --> D["业务服务"]
D --> E["外部依赖<br/>DB/缓存/第三方API"]
B --> F["指标采集<br/>耗时/状态码/错误"]
F --> G["日志/事件输出<br/>Log::write()"]
G --> H["导出器/Agent<br/>Prometheus/OTel"]
H --> I["时序数据库"]
I --> J["Grafana 仪表盘"]

[该图为概念性架构图,不直接映射具体源码文件]

核心组件

  • 日志与上下文:Log 类提供分级日志、自动上下文补全、敏感信息脱敏、采样与限流,适合作为指标事件的载体。
  • 限流中间件:ThrottleMiddleware 在 API 边界拦截超限请求并返回 429,天然适合统计 QPS、拒绝率、重试后延迟等。
  • 启动初始化:前端 Init 在引导阶段完成核心对象实例化与日志运行时初始化,是全局埋点的合适位置。
  • 统计聚合范式:订单对账与聊天日统计展示了“批量扫描+聚合统计”的模式,可用于定时汇总 QPS、错误率、耗时分位等。

章节来源

  • core/infra/log/Log.php:24-158
  • core/infra/log/Log.php:281-342
  • core/infra/log/Log.php:349-385
  • core/infra/log/Log.php:518-571
  • api/middleware/ThrottleMiddleware.php:25-90
  • front/init/Init.php:187-212
  • _'/module/order/core/service/order/OrderReconciliation.php:49-93

架构总览

下图展示从请求进入、指标采集到可视化的端到端流程,结合现有 Log 与 ThrottleMiddleware 作为采集点。

sequenceDiagram
participant C as "客户端"
participant M as "ThrottleMiddleware"
participant R as "路由/控制器"
participant S as "业务服务"
participant L as "Log 类"
participant P as "导出器/Agent"
participant T as "时序数据库"
participant G as "Grafana"
C->>M : 发起请求
M->>M : 计算窗口内计数/判定限流
M-->>C : 429/放行
M->>R : 继续管道
R->>S : 执行业务逻辑
S-->>R : 返回结果
R-->>C : 响应
M->>L : 记录指标(耗时/状态码/错误/路由)
L->>P : 写入日志/事件
P->>T : 写入时序数据
G->>T : 查询并渲染

图表来源

  • api/middleware/ThrottleMiddleware.php:25-90
  • core/infra/log/Log.php:281-342

章节来源

  • api/middleware/ThrottleMiddleware.php:25-90
  • core/infra/log/Log.php:281-342

详细组件分析

响应时间监控(API 与页面)

  • 采集点
    • API 边界:在 ThrottleMiddleware 中记录请求开始/结束时间,计算耗时,并附带 route、method、status_code、user_id、ip 等上下文。
    • 页面加载:在前端 Init 引导阶段开启全局计时,或在视图渲染前后记录耗时。
  • 指标字段
    • duration_ms、http_status、route、method、module、action、user_id、ip、scene、channel。
  • 写入方式
    • 通过 Log::write 以结构化 context 输出,便于后续抽取为指标行。
  • 注意事项
    • 高吞吐场景下启用采样与每分钟同 key 限流,避免日志风暴。
    • 敏感字段自动脱敏,避免泄露 token、密码等。
flowchart TD
Start(["请求进入"]) --> T1["记录开始时间"]
T1 --> Exec["执行路由/控制器/服务"]
Exec --> End["记录结束时间"]
End --> Calc["计算耗时/状态码"]
Calc --> Write["Log::write(context)"]
Write --> Done(["返回响应"])

图表来源

  • api/middleware/ThrottleMiddleware.php:25-90
  • core/infra/log/Log.php:281-342

章节来源

  • api/middleware/ThrottleMiddleware.php:25-90
  • core/infra/log/Log.php:281-342
  • front/init/Init.php:187-212

吞吐量统计(QPS、并发、队列长度)

  • QPS 监控
    • 基于 ThrottleMiddleware 的窗口计数,统计单位时间内的请求量与拒绝次数,计算 QPS 与拒绝率。
    • 可按 route/module/action 维度聚合。
  • 并发请求数
    • 在中间件入口处递增计数器,出口递减;或使用进程级/容器级指标(如 PHP-FPM 活跃 worker)。
  • 处理队列长度
    • 若引入异步任务队列(如 Redis/RabbitMQ),可在队列消费侧记录队列深度;当前代码未见统一队列,可复用“订单对账”的批量扫描思路,周期性统计待处理任务数量。
  • 聚合与持久化
    • 参考 OrderReconciliation 的批处理模式,定时任务扫描并汇总指标,再写入日志/导出器。
classDiagram
class ThrottleMiddleware {
+handle(next)
-throttleFor(module, action, sub) array
-reject(retryAfter) void
}
class Log {
+write(level, message, context) void
+setSampleRate(rate) void
+setMaxPerMinutePerKey(max) void
}
class OrderReconciliation {
+reconcilePendingPayments(options) array
}
ThrottleMiddleware --> Log : "记录QPS/拒绝"
OrderReconciliation ..> Log : "批处理统计范式"

图表来源

  • api/middleware/ThrottleMiddleware.php:25-90
  • core/infra/log/Log.php:281-342
  • _'/module/order/core/service/order/OrderReconciliation.php:49-93

章节来源

  • api/middleware/ThrottleMiddleware.php:25-90
  • _'/module/order/core/service/order/OrderReconciliation.php:49-93

错误率监控(异常捕获、分类、趋势)

  • 异常捕获
    • 在中间件/控制器层捕获异常,记录 error/critical 级别日志,包含堆栈、错误类型、路由、用户信息等。
  • 错误分类
    • 基于错误类型、HTTP 状态码、模块/路由维度进行分类;利用 Log 的 channel 与 scene 区分 admin/api/front。
  • 趋势分析
    • 通过日志导出器将错误事件写入时序库,按时间窗口聚合错误率;设置阈值告警。
  • 安全与脱敏
    • 利用 Log 的敏感键匹配与 URL 查询串脱敏,避免泄露凭据。
flowchart TD
EStart(["发生异常"]) --> Catch["捕获异常"]
Catch --> Classify{"分类"}
Classify --> |HTTP错误| H["记录状态码/路由"]
Classify --> |业务异常| B["记录错误类型/堆栈"]
H --> Write["Log::write(error/context)"]
B --> Write
Write --> Export["导出器/Agent"]
Export --> TSDB["时序数据库"]

图表来源

  • core/infra/log/Log.php:281-342
  • core/infra/log/Log.php:412-499

章节来源

  • core/infra/log/Log.php:281-342
  • core/infra/log/Log.php:412-499

自定义指标(业务特定性能指标)

  • 设计原则
    • 指标命名规范:metric_name{labels},标签包含 module、action、route、user_id、ip、scene、channel。
    • 数值型指标:duration_ms、qps、error_count、queue_length、tokens_used 等。
    • 事件型指标:request、response、error 等。
  • 接入方式
    • 在业务服务关键路径调用 Log::write,携带结构化 context;或通过专用指标写入函数封装。
    • 在高吞吐路径启用采样与限流,避免影响性能。
  • 示例(路径引用)
    • 参考聊天日统计的语言键与控制器,理解“按维度聚合”的指标组织方式。

章节来源

  • admin/controller/chat/DailyStatsController.php:26-51
  • _'/module/chat/languages/zh_cn/admin/chat.lang.php:206-251

指标数据存储策略

  • 推荐时序数据库
    • Prometheus:适合拉取模型,易于与 Grafana 集成,适合 QPS、错误率、耗时分位等。
    • TimescaleDB/InfluxDB:适合高写入吞吐与长周期保留,适合日志/事件转指标。
    • OpenTelemetry:统一采集与导出,兼容多后端。
  • 写入路径
    • 应用层通过 Log 输出结构化日志 → 日志采集 Agent(如 Fluent Bit/Filebeat)→ 解析为指标 → 写入时序库。
    • 或直接通过 SDK(Prometheus Client/OTel)写入。
  • 保留与降采样
    • 短期高精度(分钟级)、长期低精度(小时/天级)降采样,控制存储成本。

指标可视化方案(Grafana)

  • 数据源
    • 配置 Grafana 数据源指向时序数据库(Prometheus/TimescaleDB)。
  • 仪表盘
    • 核心面板:QPS、错误率、P50/P95/P99 耗时、拒绝率、队列长度。
    • 维度切片:按 route/module/action/user_id/ip 分组。
  • 告警
    • 基于阈值(如错误率>1%、P99>2s、QPS突降)设置告警规则,通知渠道(邮件/IM)。

依赖关系分析

  • 中间件依赖
    • ThrottleMiddleware 依赖抽象限流基类与 ApiResponse,负责在 HTTP 边界拦截与统计。
  • 日志依赖
    • Log 依赖 Session、Request、Container,用于自动补全上下文(route、user_id、ip、scene 等)。
  • 启动依赖
    • front/init/Init 在引导阶段完成核心对象实例化与日志运行时初始化,确保全局可用。
  • 系统常量
    • config/system.php 定义固定模块与保留段,有助于路由与模块维度的指标聚合。
graph LR
TM["ThrottleMiddleware"] --> API["ApiResponse"]
TM --> LOG["Log"]
INIT["front/init/Init"] --> LOG
LOG --> REQ["Request/Session/Container"]
SYS["config/system.php"] --> ROUTE["路由/模块维度"]

图表来源

  • api/middleware/ThrottleMiddleware.php:25-90
  • core/infra/log/Log.php:518-571
  • front/init/Init.php:187-212
  • config/system.php:11-34

章节来源

  • api/middleware/ThrottleMiddleware.php:25-90
  • core/infra/log/Log.php:518-571
  • front/init/Init.php:187-212
  • config/system.php:11-34

性能考量

  • 采样与限流
    • 使用 Log::setSampleRate 与 setMaxPerMinutePerKey 控制高频指标写入,避免阻塞主流程。
  • 上下文开销
    • 自动上下文补全会读取 Request/Session/Container,建议在非调试环境关闭不必要字段。
  • 存储压力
    • 日志文件按日滚动,定期清理;导出器应缓冲写入,避免频繁 IO。
  • 指标粒度
    • 高 QPS 接口优先使用聚合指标(如每秒计数、分位耗时),减少明细落盘。

故障排查指南

  • 常见问题
    • 指标缺失:检查中间件是否命中、Log 是否启用、采样率是否过高。
    • 日志风暴:调整采样率与每分钟同 key 限制,确认敏感字段未导致重复 key。
    • 错误分类不准:确认错误类型与状态码标注完整,channel/scene 是否正确。
  • 定位步骤
    • 查看当日日志文件,过滤 error/critical 级别,结合 request_id 追踪链路。
    • 在 ThrottleMiddleware 中增加 debug 日志,验证限流判定与计数。
    • 校验导出器/Agent 是否正常解析日志并写入时序库。

章节来源

  • core/infra/log/Log.php:281-342
  • core/infra/log/Log.php:349-385
  • api/middleware/ThrottleMiddleware.php:25-90

结论

通过在 HTTP 边界(中间件)与关键业务入口埋点,结合现有 Log 类的结构化上下文与采样/限流能力,可以低成本地实现 DouPHP 的性能指标收集。配合时序数据库与 Grafana,能够实现对 QPS、错误率、耗时等核心指标的实时监控与可视化,支撑容量规划与故障快速定位。

附录

  • 指标字典(建议)
    • http_request_duration_seconds{method,route,module,action,status,user_id,ip,scene,channel}
    • http_requests_total{method,route,module,action,status,scene,channel}
    • http_errors_total{type,route,module,action,scene,channel}
    • queue_length{queue_name,scene,channel}
  • 实施清单
    • 在 ThrottleMiddleware 中记录耗时与状态码。
    • 在 front/init/Init 中初始化全局计时与日志运行时。
    • 配置 Log 采样率与每分钟同 key 限制。
    • 部署导出器/Agent,将日志转为指标写入时序库。
    • 在 Grafana 创建仪表盘与告警规则。
添加日期:2026-10-05