使用 Prometheus Exporter 与 Grafana 构建 SRS 实时媒体服务器的可观测性监控
【免费下载链接】srsSRS is a simple, high-performance, AI-driven real-time media server supporting RTMP, WebRTC, HLS, HTTP-FLV, HTTP-TS, SRT, MPEG-DASH, and GB28181, with codec support for H.264, H.265, AV1, VP9, AAC, Opus, and G.711.项目地址: https://gitcode.com/GitHub_Trending/sr/srs
SRS 官方文档将可观测性定义为三件套:指标(Prometheus Exporter)、链路追踪(APM)与日志(Cloud Logging),其中 Exporter 是最容易上手、也是最常用的监控入口。本文以 SRS 仓库内 exporter 文档为骨架,结合源码逐层讲解 Exporter 的配置、指标清单与底层实现,并给出从推流到 Prometheus 采集、再到 Grafana 可视化的完整落地步骤,读完后你可以在自己的 SRS 集群上直接复刻出一套实时监控大盘。
SRS 可观测性体系与 Exporter 架构
SRS 的可观测性分为三个维度:指标(Metrics)、链路追踪(Tracing)和日志(Logging)。其中 Exporter 承担"指标"维度:它通过 HTTP 暴露 Prometheus 文本格式的指标端点,由 Prometheus 定时抓取(scrape),再由 Grafana 负责渲染与告警。
整体数据链路如下:
+-----+ +-----------+ +---------+ | SRS +--Exporter-->--| Promethus +-->--+ Grafana + +-----+ (HTTP) +-----------+ +---------+即:SRS 进程内嵌 Exporter,通过 HTTP 对外暴露/metrics端点(默认端口9972);Prometheus 按设定的scrape_interval周期拉取指标;Grafana 以 Prometheus 为数据源绘制图表。这套架构把"服务自身运行状态"与"主机节点状态"统一纳管,便于在集群规模下做横向对比。
指标、链路追踪、日志三者的分工可以参考业界通行的 observability primer:指标回答"系统现在是否健康",追踪回答"一次请求经历了什么",日志回答"发生了什么细节"。本文聚焦指标链路。
Exporter 配置详解
Exporter 由独立的exporter {}配置块控制,完整示例见 prometheus.conf 与 full.conf:
# Prometheus exporter config. # See https://prometheus.io/docs/instrumenting/exporters exporter { # Whether exporter is enabled. # Overwrite by env SRS_EXPORTER_ENABLED # Default: off enabled off; # The http api listen port for exporter metrics. # Overwrite by env SRS_EXPORTER_LISTEN # Default: 9972 # See https://github.com/prometheus/prometheus/wiki/Default-port-allocations listen 9972; # The logging label to category the cluster servers. # Overwrite by env SRS_EXPORTER_LABEL label cn-beijing; # The logging tag to category the cluster servers. # Overwrite by env SRS_EXPORTER_TAG tag cn-edge; }各参数说明如下:
| 参数 | 默认值 | 环境变量覆盖 | 含义 |
|---|---|---|---|
enabled | off | SRS_EXPORTER_ENABLED | 是否开启 Exporter,关闭时访问/metrics会返回错误 |
listen | 9972 | SRS_EXPORTER_LISTEN | Exporter 的 HTTP 监听端口,9972是 Prometheus 社区默认端口分配表中为 SRS 预留的端口 |
label | 空 | SRS_EXPORTER_LABEL | 用于区分集群服务器的日志标签,如cn-beijing(地域) |
tag | 空 | SRS_EXPORTER_TAG | 用于区分集群服务器的日志标签,如cn-edge(角色) |
label与tag会以 label 的形式出现在srs_build_info指标中,用于在多节点集群里区分"哪个地域、哪个角色"的服务器,是集群级监控的基石。
官方强烈建议使用环境变量来启用 Exporter,这样无需维护配置文件即可在容器、编排平台中快速开关。仓库提供的 prometheus.conf 是一份开箱即用的演示配置,其中exporter块已设置为enabled on; listen 9972;,并同时开启了 RTMP、HTTP API、HTTP Server 与 RTC 等模块,适合直接跑通全流程。
源码剖析:/metrics 指标端点的底层实现
理解了配置,再看源码能更清楚地知道每个配置项"去了哪里、做了什么"。
配置解析:四个 getter 与环境变量覆盖
Exporter 配置的解析集中在 srs_app_config.cpp,对应四个 getter:
get_exporter_enabled():读取exporter.enabled,默认false,可通过环境变量SRS_EXPORTER_ENABLED覆盖(源码中SRS_OVERWRITE_BY_ENV_BOOL("srs.exporter.enabled"));get_exporter_listen():读取exporter.listen,默认"9972",可被SRS_EXPORTER_LISTEN覆盖;get_exporter_label()/get_exporter_tag():默认空字符串,可被SRS_EXPORTER_LABEL/SRS_EXPORTER_TAG覆盖。
这也是文档中"推荐使用环境变量"建议的源码依据:每个配置项都有对应的SRS_EXPORTER_*环境变量通道。
独立监听器与路由挂载
Exporter 并非挂在 HTTP API(默认 1985 端口)上,而是独立的 TCP 监听器。在 srs_app_server.cpp 中,当get_exporter_enabled()为真时,会以get_exporter_listen()为端口创建SrsTcpListener(标签Exporter-Server)并开始监听:
if (config_->get_exporter_enabled()) { exporter_listener_->set_endpoint(config_->get_exporter_listen()); exporter_listener_->set_label("Exporter-Server"); if ((err = exporter_listener_->listen()) != srs_success) { return srs_error_wrap(err, "exporter server listen"); } }随后在 srs_app_server.cpp 中,将处理类SrsGoApiMetrics挂载到 HTTP 路由/metrics:
// metrics by prometheus SrsGoApiMetrics *metrics = new SrsGoApiMetrics(); metrics->assemble(); if ((err = http_api_mux_->handle("/metrics", metrics)) != srs_success) { return srs_error_wrap(err, "handle tests errors"); }而在连接接受逻辑中(srs_app_server.cpp),exporter_listener_上收到的连接会复用http_api_mux_这个 HTTP 复用器,因此访问http://<srs-host>:9972/metrics即命中SrsGoApiMetrics::serve_http。源码注释也指出:目前 Exporter 端口暂不支持 HTTPS(TODO: FIXME: Maybe should support https metrics.),生产环境如需加密建议前置反向代理。
当enabled off时,访问/metrics会返回错误码ERROR_EXPORTER_DISABLED(值为1090,见 srs_kernel_error.hpp 中定义的"Prometheus exporter is disabled")。
指标清单:serve_http 输出什么
SrsGoApiMetrics定义在 srs_app_http_api.hpp,核心实现在 srs_app_http_api.cpp。其serve_http依次输出以下 Prometheus 文本格式指标:
| 指标名 | 类型 | 含义 |
|---|---|---|
srs_node_uname_info | gauge | 主机系统信息(uname:sysname、nodename、release、version、machine),仅在 Linux/macOS 下输出 |
srs_build_info | gauge | SRS 构建信息,含 server/service id、pid、构建日期、主版本、版本号,并携带label、tag标签 |
srs_cpu_percent | gauge | SRS 进程 CPU 使用百分比 |
srs_memory | gauge | SRS 进程内存使用量(MB) |
srs_send_bytes_total | counter | SRS 累计发送字节数 |
srs_receive_bytes_total | counter | SRS 累计接收字节数 |
srs_streams | gauge | 当前并发流数量 |
srs_clients | gauge | 当前在线客户端数量 |
srs_clients_total | counter | 客户端累计连接数 |
srs_clients_errs_total | counter | 客户端累计错误数 |
其中srs_build_info中携带的label/tag正是来自配置块中的exporter.label与exporter.tag(见 srs_app_http_api.cpp 中if (!label_.empty()) ... if (!tag_.empty())的条件输出逻辑),这就是集群分类监控的实现位置。
业务计数指标(发送/接收字节、流数、客户端数)则来自全局统计单例SrsStatistic::dumps_metrics(srs_app_statistic.cpp),它从 KBPS 采样器与流/客户端表中取数:
send_bytes = kbps_->get_send_bytes(); recv_bytes = kbps_->get_recv_bytes(); nstreams = streams_.size(); nclients = clients_.size(); total_nclients = nb_clients_; nerrs = nb_errs_;单测 srs_utest_ai16.cpp 中的SrsGoApiMetricsTest.ServeHttpSuccess会校验响应的 Prometheus 格式,包括# HELP srs_build_info、srs_cpu_percent、srs_memory、srs_send_bytes_total等指标是否按预期输出,可作为理解指标语义的参考。
另外,srs_app_latest_version.cpp 在向官方版本服务上报运行特征时,也会通过get_exporter_enabled()附带prom功能标记,说明 Exporter 是 SRS 官方认可的受支持能力。
实战一:构建并启动 SRS Exporter
下面从零开始跑通"推流 → 采集 → 查询"全链路。
1. 编译并启动 SRS(5.0.86+)
在仓库trunk目录下编译并启动:
./configure && make env SRS_ENV_ONLY=on SRS_EXPORTER_ENABLED=on SRS_LISTEN=1935 \ ./objs/srs -e./configure && make:完成默认特性的编译;SRS_ENV_ONLY=on:仅使用环境变量配置 SRS,不加载配置文件;SRS_EXPORTER_ENABLED=on:开启 Exporter(等价于配置块exporter { enabled on; });SRS_LISTEN=1935:RTMP 监听端口;./objs/srs -e:以环境变量模式启动。
启动后打开http://localhost:9972/metrics即可看到上述全部指标。也可以改用配置文件conf/prometheus.conf启动演示(对应仓库内 prometheus.conf,其中exporter { enabled on; listen 9972; }已就绪)。
2. 用 FFmpeg 推一路直播流
使用官方编码器镜像推流,验证接收字节指标随流增长:
docker run --rm -it ossrs/srs:encoder ffmpeg -re -i doc/source.flv -c copy \ -f flv rtmp://host.docker.internal/live/livestream3. 启动 node_exporter 采集主机指标
Exporter 只反映 SRS 进程自身,主机层指标(CPU、内存、磁盘、网络)需要 node_exporter:
docker run --rm -p 9100:9100 prom/node-exporter打开http://localhost:9100/metrics即可验证。生产环境强烈建议从其官方 Release 下载二进制直接运行,而不是在每台主机上常驻 Docker 容器。
4. 编写 prometheus.yml 并启动 Prometheus
创建prometheus.yml,同时配置 node 与 srs 两个抓取任务:
scrape_configs: - job_name: "node" metrics_path: "/metrics" scrape_interval: 5s static_configs: - targets: ["host.docker.internal:9100"] - job_name: "srs" metrics_path: "/metrics" scrape_interval: 5s static_configs: - targets: ["host.docker.internal:9972"]注意:这里将
scrape_interval设为5s,而 Prometheus 的默认值是1m(一分钟)。对直播场景而言,默认值粒度过粗,建议按监控精度需求显式调小。
启动 Prometheus:
docker run --rm -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \ -p 9090:9090 prom/prometheus5. 用 PromQL 查询输入码率
打开http://localhost:9090/targets查看两个抓取目标是否 UP,然后在http://localhost:9090/graph中执行查询:
rate(srs_receive_bytes_total[10s])*8该查询计算 SRS 最近 10 秒接收字节的变化率并乘以 8,即得到输入码率(bit/s)。推流过程中曲线应随码率波动,直观验证"Exporter → Prometheus"链路已经打通。若要监控输出码率,将指标替换为srs_send_bytes_total即可。
实战二:接入 Grafana 可视化大盘
Prometheus 适合查询与告警,日常观察与汇报更常用 Grafana。
1. 启动 Grafana
docker run --rm -it -p 3000:3000 \ -e GF_SECURITY_ADMIN_USER=admin \ -e GF_SECURITY_ADMIN_PASSWORD=12345678 \ -e GF_USERS_DEFAULT_THEME=light \ grafana/grafana浏览器打开http://localhost:3000/,使用admin/12345678登录。
2. 通过 API 添加 Prometheus 数据源
curl -s -H "Content-Type: application/json" \ -XPOST http://admin:12345678@localhost:3000/api/datasources \ -d '{ "name": "prometheus", "type": "prometheus", "access": "proxy", "isDefault": true, "url": "http://host.docker.internal:9090" }'其中access: "proxy"表示由 Grafana 服务端代理转发查询,isDefault: true使其成为默认数据源,url指向 Prometheus 的 9090 端口。
3. 导入 HelloWorld 仪表盘
data=$(curl https://raw.githubusercontent.com/ossrs/srs-grafana/main/dashboards/helloworld-import.json 2>/dev/null) curl -s -H "Content-Type: application/json" \ -XPOST http://admin:12345678@localhost:3000/api/dashboards/db \ --data-binary "{\"dashboard\":${data},\"overwrite\":true,\"inputs\":[],\"folderId\":0}"第一条命令从 srs-grafana 仓库拉取 HelloWorld 仪表盘 JSON,第二条命令通过 Grafana Dashboard API 导入。之后打开http://localhost:3000/dashboards即可看到导入的仪表盘。
官方还提供了更多仪表盘(包含 SRS 各指标的面板组合),存放在 srs-grafana 仓库的dashboards目录下,可按需导入。任何改进都欢迎提交补丁,SRS 社区持续维护这套可观测性资产。
生产环境实践建议
- 集群分类:为每个 SRS 节点设置不同的
label(地域)与tag(角色,如cn-edge、cn-origin),配合srs_build_info{label="...", tag="..."}即可在 Grafana 中按节点维度拆分监控,方便定位"哪台边缘节点异常"。 - 抓取间隔:直播业务指标变化快,建议
scrape_interval设为 5s~15s;若集群节点多、指标量大,可适当放宽以降低 Prometheus 压力。 - 端口规划:
9972是社区默认端口分配表中 SRS 预留端口;若与既有端口冲突,通过SRS_EXPORTER_LISTEN或exporter { listen ...; }调整,并同步修改 Prometheus 的targets。 - 安全边界:Exporter 端口当前不支持 HTTPS,且
/metrics无需鉴权即可访问,生产环境建议将 9972 端口收敛在内网/监控网段,或在前置网关做访问控制。 - 从源码验证:本文涉及的指标输出逻辑(srs_app_http_api.cpp)、配置解析(srs_app_config.cpp)与统计取数(srs_app_statistic.cpp)均可直接在仓库中对照阅读,单测 srs_utest_ai16.cpp 则给出了指标响应的格式基线。
参考文件索引
- exporter 官方文档:本文骨架来源;
- prometheus.conf:开箱即用的 Exporter 演示配置;
- full.conf:完整配置参考中的 exporter 段;
- srs_app_config.cpp:Exporter 四个配置项的解析与环境变量覆盖;
- srs_app_server.cpp:Exporter 独立监听器的创建与启停;
- srs_app_http_api.cpp:
/metrics端点与全部指标的输出实现; - srs_app_http_api.hpp:
SrsGoApiMetrics处理类声明; - srs_app_statistic.cpp:全局统计指标取数实现;
- srs_kernel_error.hpp:
ERROR_EXPORTER_DISABLED错误码定义; - srs_utest_ai16.cpp:
/metrics响应格式的单元测试。
【免费下载链接】srsSRS is a simple, high-performance, AI-driven real-time media server supporting RTMP, WebRTC, HLS, HTTP-FLV, HTTP-TS, SRT, MPEG-DASH, and GB28181, with codec support for H.264, H.265, AV1, VP9, AAC, Opus, and G.711.项目地址: https://gitcode.com/GitHub_Trending/sr/srs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考