音视频API与传统Web API的监控差异很大。一个播放请求可能经历鉴权、频道创建、流媒体转发、转码、录制等多个环节,任何一个环节的延迟增加或错误率上升,都会直接影响用户体验。Prometheus、Grafana和AlertManager的组合能够把分散在各服务中的指标统一收集起来,并通过可视化和告警快速暴露问题。下面将围绕指标设计、告警规则和排障实践展开。

音视频API的指标设计与Prometheus采集
音视频API监控的第一步是定义合适的指标。传统Web API通常只关心请求量、错误率和响应时间,但音视频场景还需要关注首帧时间、缓冲次数、丢包率、码率、并发会话数、转码任务积压等。这些指标能反映播放链路的质量,而不仅仅是HTTP层是否返回200。比如一个请求虽然成功建立会话,但首帧耗时超过3秒,用户已经流失,这在普通HTTP监控中无法体现。
Prometheus的指标类型可以很好地对这些场景建模。Counter适合统计请求总数、转码失败次数;Gauge适合记录当前在线会话数、推流端实时码率;Histogram适合统计请求耗时、首帧时间分布;Summary则可以提供客户端计算的分位数。对于音视频API,建议对每个核心接口建立统一的耗时Histogram,并附带handler、status、stream_type等标签,方便后续用PromQL切割分析。
下面以Go语言为例,展示如何在音视频API服务中定义并暴露这些指标。代码使用promhttp处理器暴露/metrics接口,并定义了请求耗时Histogram和当前会话数Gauge。
package main
import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
requestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "media_api_request_duration_seconds",
Help: "Duration of media API requests in seconds",
Buckets: prometheus.DefBuckets,
},
[]string{"handler", "status"},
)
activeSessions = prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "media_api_active_sessions",
Help: "Current number of active media sessions",
},
)
)
func init() {
prometheus.MustRegister(requestDuration, activeSessions)
}
func streamHandler(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// 模拟会话建立逻辑
activeSessions.Inc()
defer activeSessions.Dec()
// 实际业务处理
time.Sleep(20 * time.Millisecond)
requestDuration.WithLabelValues("/api/v1/stream", "200").Observe(time.Since(start).Seconds())
w.WriteHeader(http.StatusOK)
}
func main() {
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/api/v1/stream", streamHandler)
http.ListenAndServe(":8080", nil)
}
采集侧需要在Prometheus配置文件中添加抓取任务。音视频服务可能部署在Kubernetes中,可以通过服务发现自动找到Pod的/metrics端点。如果服务是独立部署,也可以使用静态配置。下面是一个静态配置示例,抓取间隔设置为15秒,并标注服务名称。
scrape_configs:
- job_name: 'media-api'
scrape_interval: 15s
static_configs:
- targets: ['10.0.1.12:8080', '10.0.1.13:8080']
labels:
service: 'media-api'
region: 'cn-north'
告警规则与AlertManager分级通知
指标采集之后,需要将关键异常转化为告警。音视频API的告警规则应该避免使用单一阈值,因为流量波动会导致误报。比如错误率在深夜流量低时可能突然升高,但实际影响很小。更好的做法是结合窗口函数和持续时长,例如5分钟内错误率超过5%并且持续5分钟才触发。对于延迟类指标,应使用Histogram的分位数告警,而不是平均值,因为P99更能反映长尾问题。
下面这个Prometheus规则文件定义了两个核心告警。第一个监控5xx错误率,使用sum(rate())聚合所有音视频API请求;第二个监控推流首帧时间P99,使用histogram_quantile函数。所有规则都添加了severity和service标签,便于AlertManager路由。
groups:
- name: media-api-alerts
rules:
- alert: MediaAPIHighErrorRate
expr: |
sum(rate(media_api_request_duration_seconds_count{status=~"5.."}[5m]))
/
sum(rate(media_api_request_duration_seconds_count[5m])) > 0.05
for: 5m
labels:
severity: critical
service: media-api
annotations:
summary: "音视频API错误率超过5%"
description: "服务{{ $labels.service }}在5分钟内的错误率为{{ $value | humanizePercentage }}"
- alert: MediaAPIHighFirstFrameLatency
expr: |
histogram_quantile(0.99,
sum(rate(media_api_first_frame_seconds_bucket[5m])) by (le)
) > 3
for: 10m
labels:
severity: warning
service: media-api
annotations:
summary: "音视频首帧耗时P99超过3秒"
description: "服务{{ $labels.service }}的首帧P99延迟为{{ $value }}秒"
AlertManager的作用是对告警进行去重、分组、静默和路由。在音视频API场景中,同一个底层故障可能触发多个接口的告警,如果直接发送会淹没运维人员。AlertManager可以按service或cluster分组,将同一组告警合并成一条通知。下面的配置将来自media-api服务的critical告警发送到企业微信和邮件,warning告警只发送到邮件,并设置了2小时的静默窗口用于夜间维护。
route:
group_by: ['alertname', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'default-receiver'
routes:
- match:
service: 'media-api'
severity: 'critical'
receiver: 'media-critical'
- match:
service: 'media-api'
severity: 'warning'
receiver: 'media-warning'
receivers:
- name: 'media-critical'
webhook_configs:
- url: 'http://alert-forwarder:5000/wechat'
email_configs:
- to: 'oncall@media.ipipp.com'
- name: 'media-warning'
email_configs:
- to: 'dev-team@media.ipipp.com'
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['service']
Grafana可视化与排障实践
Grafana通过Prometheus数据源将指标变成可读的图表。对于音视频API,推荐搭建两个核心Dashboard:一个是全局总览,展示QPS、错误率、P99延迟、活跃会话数、转码队列长度;另一个是会话明细,按流ID、用户ID、边缘节点等维度下钻。Grafana支持Heatmap面板直接展示Histogram数据,可以直观看到延迟分布随时间的变化。
以下PromQL查询用于展示各接口的错误率趋势。它使用label_replace将接口路径归并,避免高基数问题。面板设置为时间序列图,单位选择百分比。
sum(rate(media_api_request_duration_seconds_count{status=~"5.."}[5m])) by (handler)
/
sum(rate(media_api_request_duration_seconds_count[5m])) by (handler)
排障时,当收到MediaAPIHighErrorRate告警,第一件事是打开Grafana对应的错误率面板,确认是哪个handler或节点贡献了错误。可以进一步用PromQL过滤出具体实例:
topk(5,
sum by (instance, handler) (
rate(media_api_request_duration_seconds_count{status=~"5.."}[5m])
)
)
对于首帧耗时告警,可以查看Heatmap面板,观察P99和P50的差距。如果P50正常但P99异常,通常意味着部分边缘节点负载过高或特定码流格式转码慢。此时可以结合节点的CPU、网络丢包率以及转码任务积压指标一起分析。Grafana的Ad-hoc过滤器允许在面板上临时添加过滤条件,而无需修改查询,这在应急排障时非常高效。
监控落地的常见误区与优化建议
实践中容易犯的错误之一是标签设计不当。音视频API往往包含流ID、用户ID等高基数字段,如果直接作为Prometheus标签,会导致内存爆炸。正确的做法是只保留低基数标签,如handler、status、region、node,而将流ID、用户ID放到日志系统或通过Exemplar关联。
另一个误区是告警阈值拍脑袋。建议先采集至少两周的指标,利用Grafana的统计功能观察指标的分位数和周期特征,再设置动态阈值或分时段阈值。AlertManager的inhibit_rules和沉默功能可以显著降低告警噪音,但必须确保核心告警不会被抑制。
最后,监控系统本身也需要高可用。Prometheus可以部署为两个副本,使用相同的抓取配置,AlertManager集群通过gossip协议同步静默状态。Grafana使用外部数据库存储面板配置,并通过provisioning实现配置即代码。这样即使单个节点故障,监控告警链路也不会中断。
PrometheusGrafanaAlertManager修改时间:2026-10-03 11:10:30