27. 监控与告警:使用 Prometheus 收集指标、Grafana 可视化、关键指标告警

信令服务器跑起来了,功能也正常了。但说实话,这只是第一步。

真正让我头疼的,是线上环境里那些「看不见的问题」。比如内存悄悄涨了、连接数突然飙升、某个信令响应慢了 200 毫秒。这些问题,用户不会直接告诉你,但他们会觉得「卡」、「连不上」、「体验差」。

所以这一章,我们来聊聊怎么给信令服务器装上「监控眼睛」。我会用 Prometheus 收集指标,用 Grafana 做可视化,再配上关键指标的告警规则。嗯,这套组合拳,我在好几个项目里都用过,效果不错。

为什么需要监控信令服务器?

你可能会想:「我的信令服务器就几百行代码,有必要搞这么复杂吗?」

我以前也这么觉得。直到有一次,一个客户反馈说视频通话经常断连。我查了半天日志,才发现是信令服务器的 WebSocket 连接数超过了系统限制,导致新连接被拒绝。但日志里只有零星的错误信息,根本看不出趋势。

如果有监控,我就能提前看到连接数的增长曲线,在达到上限之前扩容或者优化。说白了,监控不是为了「出问题时查原因」,而是为了「在出问题之前就发现苗头」。

核心思路: 信令服务器暴露 /metrics 端点 → Prometheus 定期拉取 → Grafana 展示仪表盘 → 告警规则触发通知。

第一步:在信令服务器中暴露指标

我用的是 Node.js 写的信令服务器,配合 prom-client 这个库来暴露指标。你如果用的是其他语言,也有对应的 Prometheus 客户端库。

先安装依赖:

npm install prom-client

然后在信令服务器中,添加一个 /metrics 端点:

const client = require('prom-client');
const express = require('express');
const app = express();

// 创建指标收集器
const collectDefaultMetrics = client.collectDefaultMetrics;
collectDefaultMetrics({ timeout: 5000 });

// 自定义指标:当前 WebSocket 连接数
const activeConnections = new client.Gauge({
  name: 'signaling_active_connections',
  help: '当前活跃的 WebSocket 连接数'
});

// 自定义指标:信令消息处理耗时(直方图)
const messageDuration = new client.Histogram({
  name: 'signaling_message_duration_seconds',
  help: '信令消息处理耗时(秒)',
  buckets: [0.01, 0.05, 0.1, 0.5, 1, 2]
});

// 自定义指标:信令消息总数(计数器)
const messageTotal = new client.Counter({
  name: 'signaling_messages_total',
  help: '信令消息总数',
  labelNames: ['type'] // 按消息类型区分
});

// 暴露 /metrics 端点
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', client.register.contentType);
  res.end(await client.register.metrics());
});

// 在 WebSocket 连接建立时更新指标
wss.on('connection', (ws) => {
  activeConnections.inc();
  ws.on('close', () => activeConnections.dec());
});

// 在处理信令消息时记录耗时
function handleMessage(type, handler) {
  return (data) => {
    const end = messageDuration.startTimer();
    handler(data);
    end();
    messageTotal.inc({ type });
  };
}
我的习惯: 除了默认的 Node.js 指标(内存、CPU、事件循环延迟),我还会加几个业务指标。比如「房间数」、「信令消息类型分布」、「连接建立耗时」。这些指标能帮你快速定位是系统问题还是业务逻辑问题。

第二步:配置 Prometheus 拉取指标

Prometheus 的配置很简单。创建一个 prometheus.yml

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'signaling-server'
    static_configs:
      - targets: ['localhost:3000']  # 信令服务器的地址
    metrics_path: '/metrics'

然后启动 Prometheus:

./prometheus --config.file=prometheus.yml

启动后,访问 http://localhost:9090 就能看到 Prometheus 的 Web 界面。在「Status → Targets」里,如果看到信令服务器的状态是 UP,说明拉取成功了。

注意: 如果信令服务器有多个实例,记得在 targets 里列出所有地址。我见过有人只配了一个实例,结果另一个实例挂了都不知道。

第三步:用 Grafana 可视化指标

Prometheus 自带的图表功能比较基础。真正好用的是 Grafana。

先添加 Prometheus 数据源:

  1. 打开 Grafana(默认 http://localhost:3001
  2. 进入 Configuration → Data Sources → Add data source
  3. 选择 Prometheus,URL 填 http://localhost:9090
  4. 点击 Save & Test,看到绿色提示就成功了

然后创建一个仪表盘,添加几个关键面板:

面板名称 查询语句(PromQL) 说明
活跃连接数 signaling_active_connections 当前 WebSocket 连接数
消息处理耗时(P99) histogram_quantile(0.99, rate(signaling_message_duration_seconds_bucket[5m])) 99% 的消息在多少毫秒内处理完
消息处理速率 rate(signaling_messages_total[1m]) 每秒处理的消息数
内存使用量 nodejs_heap_size_used_bytes Node.js 堆内存使用量
事件循环延迟 nodejs_eventloop_lag_seconds 事件循环的延迟,超过 1 秒就要注意了

下面是我常用的一个仪表盘布局,你可以参考:

信令服务器监控仪表盘布局 活跃连接数 1,247 当前 WebSocket 连接 ▲ 较昨日 +12% 消息处理耗时 P99 45ms 99% 消息在此时间内完成 ▲ 较昨日 -5ms 消息处理速率 342/s 每秒处理的消息数 ▼ 较昨日 -8% 内存使用量趋势 当前 256MB 事件循环延迟 最近 6 分钟

第四步:设置关键指标告警

光有仪表盘还不够。你不可能 24 小时盯着屏幕看。所以告警才是监控的灵魂。

在 Prometheus 里配置告警规则,创建一个 alerts.yml

groups:
  - name: signaling-server-alerts
    rules:
      - alert: 连接数过高
        expr: signaling_active_connections > 1000
        for: 1m
        annotations:
          summary: "信令服务器连接数超过 1000"
          description: "当前连接数:{{ $value }}"

      - alert: 消息处理延迟过高
        expr: histogram_quantile(0.99, rate(signaling_message_duration_seconds_bucket[5m])) > 0.5
        for: 2m
        annotations:
          summary: "信令消息处理延迟超过 500ms"
          description: "P99 延迟:{{ $value }}s"

      - alert: 内存使用率过高
        expr: nodejs_heap_size_used_bytes / nodejs_heap_size_total_bytes > 0.8
        for: 3m
        annotations:
          summary: "Node.js 堆内存使用率超过 80%"
          description: "当前使用率:{{ $value | humanizePercentage }}"

      - alert: 事件循环延迟过高
        expr: nodejs_eventloop_lag_seconds > 1
        for: 30s
        annotations:
          summary: "事件循环延迟超过 1 秒"
          description: "当前延迟:{{ $value }}s"

然后在 prometheus.yml 中引用这个规则文件:

rule_files:
  - 'alerts.yml'
避坑指南: 我曾经把告警阈值设得太低,结果半夜被频繁的告警吵醒。后来我学乖了:告警阈值要留有余量,比如连接数上限是 1500,我设告警在 1000。这样你有时间处理,而不是等系统挂了才收到告警。

第五步:配置告警通知(以钉钉为例)

Prometheus 本身不直接发通知。你需要用 Alertmanager 来转发告警。

安装 Alertmanager 后,配置 alertmanager.yml

route:
  receiver: 'dingtalk'

receivers:
  - name: 'dingtalk'
    webhook_configs:
      - url: 'https://oapi.dingtalk.com/robot/send?access_token=你的Token'
        send_resolved: true

这样,当告警触发时,钉钉群就会收到消息。你也可以配置邮件、Slack、企业微信等。

监控体系的核心逻辑

最后,我用一张图总结一下整个监控体系的流程:

信令服务器 /metrics 端点 Prometheus 拉取指标 Grafana 可视化仪表盘 Alertmanager 告警规则评估 通知渠道 钉钉/邮件/Slack

说白了,这套体系就是:信令服务器暴露指标 → Prometheus 拉取并存储 → Grafana 展示 → Alertmanager 在异常时通知你。

我个人的经验是,先把最基础的几个指标(连接数、延迟、内存)监控起来,再慢慢加业务指标。别想着一步到位,监控是迭代出来的。

总结一下:
  • 用 prom-client 在信令服务器中暴露 /metrics 端点
  • Prometheus 定期拉取指标,存储为时间序列数据
  • Grafana 连接 Prometheus 数据源,创建可视化仪表盘
  • 配置告警规则,通过 Alertmanager 发送通知
  • 关键指标:连接数、消息处理耗时、内存使用率、事件循环延迟

好了,这一章的内容就到这里。监控不是一锤子买卖,上线后要根据实际情况不断调整阈值和指标。你想想看,如果连服务器状态都看不清,怎么敢说自己的信令服务是稳定的呢?