监控指南

September 5, 2026 · View on GitHub

English中文

本指南涵盖 Mortred Model Server 监控体系的完整生命周期:部署、配置、指标含义、仪表盘解读、告警响应与故障排查。适用于运维人员(SRE / DevOps)与服务管理员。

架构概览

┌─────────────────────────────────────────────────────────────┐
│                       监控数据流                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌──────────┐   /metrics    ┌──────────────┐               │
│  │  网关     │ ───────────→ │              │               │
│  │ (:8080)  │               │  Prometheus  │               │
│  └──────────┘               │  (:9090)     │               │
│                              │  抓取+存储    │               │
│  ┌──────────┐   /metrics    │  +告警评估    │──→ 告警通知    │
│  │  监督器   │ ───────────→ │              │   (可选)      │
│  │ (:8787)  │               └──────┬───────┘               │
│  └──────────┘                      │                        │
│                              ┌──────▼───────┐               │
│  ┌──────────┐   /metrics    │   Grafana    │               │
│  │ 模型服务器 │ ───────────→ │  (:3000)     │               │
│  │(仅环回)   │               │  可视化面板   │               │
│  └──────────┘               └──────────────┘               │
└─────────────────────────────────────────────────────────────┘

默认刮取目标是网关 :8080/metrics(环回上未设 MORTRED_METRICS_TOKEN 时公开; 非环回网关必须设置 scrape token)。监督器 :8787/api/v1/metrics 需要管理 Bearer token。模型 /metrics 仅环回,且在监督器注入了 MORTRED_AUTH_TOKEN 时需要同一 Bearer。不要为了刮指标而映射模型端口。

快速开始

方式一:Docker Compose 一键部署(推荐)

export GRAFANA_ADMIN_PASSWORD="$(openssl rand -hex 16)"
docker compose -f deploy/docker-compose.monitoring.yml up -d
# Grafana: http://localhost:3000(用户 admin / $GRAFANA_ADMIN_PASSWORD)
# Prometheus: http://localhost:9090(仅环回)
# 注意:Linux 上需将 prometheus.yml 中网关 target 的 localhost
# 改为 host.docker.internal

方式二:裸机部署

sudo apt install prometheus grafana
sudo cp deploy/prometheus.yml /etc/prometheus/prometheus.yml
sudo cp deploy/alert-rules.yml /etc/prometheus/alert-rules.yml
sudo systemctl restart prometheus

方式三:Prometheus 单独运行

prometheus --config.file=deploy/prometheus.yml --storage.tsdb.path=/tmp/prom-data

指标来源

组件端口端点说明
网关:8080/metrics推理入口(环回上未设 token 时公开;非环回必须 scrape token)
监督器:8787/api/v1/metrics进程管理(需要 Bearer MORTRED_API_TOKEN
模型服务器环回 :9001-9084/metrics与 Prometheus 同一网络命名空间;不要映射这些端口

添加新模型抓取

仅当 Prometheus 能打到模型的环回端口时(host 网络,或与 systemd 同机)。 永远不要为了刮指标而 docker publish 模型端口。

  - job_name: mortred-model-yolov5
    static_configs:
      - targets: ['localhost:9053']
        labels: { component: model, model: yolov5 }

指标参考

可用性(3 个)— "服务是否活着"

指标类型说明
mortred_upgauge进程存活 (1=活)
mortred_readygauge有可用 worker (1=就绪)
upgaugePrometheus 可抓取 (1=可达)

mortred_up vs up:前者是进程自报告,后者是 Prometheus 外部探测。up == 0 是更可靠的宕机信号。

流量(3 个)— "有多少请求"

指标类型标签说明
mortred_http_requests_totalcountermodel, method, statusHTTP 请求累计
mortred_http_request_duration_mshistogrammodel, method, status请求耗时(毫秒)
mortred_queue_rejected_totalcountermodel429 拒绝累计
# 每秒请求数
sum(rate(mortred_http_requests_total[5m]))

# 按模型的 p95 延迟
histogram_quantile(0.95, sum(rate(mortred_http_request_duration_ms_bucket[5m])) by (le, model))

# 5xx 错误率
100 * sum(rate(mortred_http_requests_total{status=~"5.."}[5m])) by (model)
  / sum(rate(mortred_http_requests_total[5m])) by (model)

推理(7 个)— "模型本身表现"

指标类型说明
mortred_inference_duration_mshistogram模型推理耗时(不含排队)
mortred_queue_wait_duration_mshistogram等待 worker 耗时
mortred_inference_success_totalcounter成功推理累计
mortred_inference_failure_totalcounter失败推理累计
mortred_model_output_contract_failures_totalcounter???? dtype/shape/buffer ??????
mortred_workers_busygauge繁忙 worker 数
mortred_workers_availablegauge空闲 worker 数
mortred_queue_depthgauge排队深度

诊断:p95 延迟高时,先看 queue_depth——深排队 → 容量不足(加 worker);浅排队但慢 → 模型/GPU 问题。

批处理(2 个)— "批处理是否有效"

指标类型说明
mortred_batch_sizehistogram实际执行批大小
mortred_batch_window_wait_mshistogram批收集窗口等待
# 平均批大小(> 1.5 说明有效)
sum(mortred_batch_size_sum) by (model) / sum(mortred_batch_size_count) by (model)

异步任务(3 个)— "长任务状态"

指标类型说明
mortred_async_jobs_totalcounter按状态计数(submitted/running/done/failed/timeout)
mortred_async_queue_depthgauge异步队列深度
mortred_async_job_duration_mshistogram异步任务耗时

监督器(3 个)— "进程管理"

指标类型说明
mortred_supervisor_stategauge进程状态码
mortred_supervisor_readygauge进程就绪 (1)
mortred_supervisor_restarts_totalcounter重启累计

状态码

状态含义
0stopped已停止
1starting启动中
2running正常运行
3backoff重启退避中
4failed崩溃循环放弃

告警参考

告警概览(12 条 × 5 组)

可用性(4 条)

告警级别触发含义响应
GatewayDowncritical网关 30 秒不可达推理流量全断检查网关进程
SupervisorDowncritical监督器 60 秒不可达进程管理丢失检查 supervisor
ModelServerDownwarning模型 60 秒不可达单模型不可用查看该模型日志
ModelNotReadywarning就绪探针失败 2 分钟进程在但不可用检查模型加载

性能(5 条)

告警级别触发含义响应
HighQueueDepthwarning深度 > 20 持续 60 秒排队过长加 worker 或扩容
OverloadRejectionswarning429 > 0.1/s 持续 2 分钟开始拒绝请求增大 max_queue_depth
HighLatencywarningp95 > 2000ms 持续 5 分钟推理变慢检查 GPU / 模型
HighErrorRatecritical5xx > 5% 持续 2 分钟大量推理失败查看模型日志
AllWorkersBusycritical0 空闲 worker 持续 2 分钟可能卡死检查 stuck-worker

异步(2 条)

告警级别触发响应
AsyncQueueFullwarning异步深度 > 10 持续 2 分钟检查异步 worker 数
AsyncTimeoutswarning超时 > 0.05/s检查 async_timeout

批处理(1 条)

告警级别触发响应
BatchNotCoalescinginfo平均批 < 1.5 持续 10 分钟检查并发量和 delay

监督器(1 条)

告警级别触发响应
RestartStormcritical重启 > 0.2/s 持续 2 分钟查崩溃原因

级别与响应

级别含义通知响应时间
critical服务不可用电话/短信< 5 分钟
warning性能退化Slack/邮件< 30 分钟
info优化建议仪表盘下次巡检

自定义告警

- alert: MortredCustomGPUHigh
  expr: your_gpu_metric > 90
  for: 300s
  labels: { severity: warning }
  annotations:
    summary: "GPU 使用率过高"
curl -X POST http://localhost:9090/-/reload  # 热加载

Grafana 仪表盘

导入

Dashboard → Import → 上传 deploy/grafana-dashboard.json → 选择 Prometheus 数据源 → Import

面板解读

第一行:全局概览

#面板看什么
1服务可用性全绿 = 正常;红 = 有宕机
2推理速率流量趋势;突降 = 异常
3错误率正常 < 1%;突升 = 模型问题
4过载拒绝非零 = 过载开始

第二行:性能

#面板看什么
5延迟 p50/p95/p99p99 突刺 = 个别慢请求
6队列深度持续上升 = 容量不足
7Worker 状态busy = total → 满载

第三行:批处理与异步

#面板看什么
8批大小平均 > 1.5 = 批有效
9批窗口等待过高 = delay 太大
10异步任务done 上升正常;timeout 上升异常

第四行:系统健康

#面板看什么
11异步队列深度> 10 = 积压
12进程状态2=绿(运行)、4=红(失败)
13重启率非零持续 = 崩溃循环

故障排查

Prometheus 抓取失败

curl -s http://localhost:9090/api/v1/targets | \
  jq '.data.activeTargets[] | select(.health != "up") | {job: .labels.job, error: .lastError}'

常见原因:模型未运行 / 端口错误 / Docker 网络(用 host.docker.internal)

指标缺失

curl -s http://localhost:8080/metrics | head -5

常见原因:进程未运行 / 端口不对 / supervisor 需要 Bearer token / Prometheus 在 Docker 里仍指向 localhost 而不是 host.docker.internal

告警不触发

curl -s http://localhost:9090/api/v1/rules | \
  jq '.data.groups[].rules[] | select(.type == "alerting") | {name, state}'

curl -s 'http://localhost:9090/api/v1/query?query=mortred_queue_depth' | jq '.data.result'

常见原因:表达式标签不匹配 / for 时长未达到 / 告警被静默

Grafana 面板无数据

curl -s http://localhost:3000/api/datasources | jq '.[] | {name, type, url}'

确保 Prometheus URL 正确,在 Explore 中手动测试查询。

手动验证命令汇总

# 网关
curl -s http://localhost:8080/metrics | head -20
curl -s http://localhost:8080/metrics | grep mortred_http_requests_total

# 模型服务器(在跑模型的那台机器上打环回;不要 -p 这些端口)
curl -s http://localhost:9002/metrics | grep mortred_up
curl -s http://localhost:9002/metrics | grep mortred_queue_depth
curl -s http://localhost:9002/metrics | grep mortred_workers
curl -s http://localhost:9002/metrics | grep mortred_batch_size
curl -s http://localhost:9002/metrics | grep mortred_async

# 监督器
curl -s -H "Authorization: Bearer $MORTRED_API_TOKEN" \
  http://localhost:8787/api/v1/metrics

# Prometheus
curl -s http://localhost:9090/api/v1/targets | \
  jq '.data.activeTargets[] | {job: .labels.job, health: .health}'

curl -s http://localhost:9090/api/v1/alerts | \
  jq '.data.alerts[] | {name: .labels.alertname, state}'

# 手动查询
curl -s 'http://localhost:9090/api/v1/query?query=mortred_up' | jq .
curl -s 'http://localhost:9090/api/v1/query?query=rate(mortred_http_requests_total[5m])' | jq .

最佳实践

抓取间隔与保留

global:
  scrape_interval: 15s     # 高流量可降到 5s
  evaluation_interval: 15s
prometheus --storage.tsdb.retention.time=30d  # 保留 30 天

阈值调优

指标初始值调优建议
queue_depth> 20观察 1 周按 P99 调
p95 latency> 2000ms按模型类型分组(分类 < 100ms,检测 < 500ms)
5xx rate> 5%高可靠可降到 1%
restart rate> 0.2/s偶尔重启可放宽到 0.1/min

覆盖度检查清单

  • Gateway :8080 抓取正常
  • Supervisor :8787 仅在 Prometheus 配了 Bearer 时抓取
  • 模型 scrape job 只出现在 Prometheus 与模型共享环回的地方
  • Grafana / Prometheus 端口在环回;Grafana 密码不是镜像默认值
  • 12 条告警规则全部加载
  • Grafana 13 面板有数据
  • 配置了至少一个通知渠道
  • 做过一次告警演练(停一个模型验证触发)