一、为什么需要监控SignalR服务端性能

SignalR作为.NET生态下优秀的实时通信框架,在在线聊天、实时游戏、金融行情推送等场景中广泛应用。但随着连接数增长,服务端可能面临连接数暴增、消息积压、CPU/内存飙升等问题。想象一下,当你的在线教育平台突然涌入上万学生时,若无法实时掌握服务端状态,系统可能毫无征兆地崩溃。

典型问题场景

  • 连接数超过服务器承载上限导致拒绝服务
  • 消息吞吐量突增引发线程池饥饿
  • 内存泄漏使服务间歇性卡顿

通过Prometheus+Grafana这套云原生监控组合拳,我们可以像给SignalR装上"心电图仪",实时捕捉以下关键指标:

  1. 当前活跃连接数(反映服务负载)
  2. 消息收发速率(衡量处理能力)
  3. 内存/CPU消耗(资源健康度)

二、搭建监控环境基础

2.1 安装Prometheus基础组件

以Docker环境为例(技术栈:.NET Core 6 + Docker):

# 创建监控专用网络
docker network create monitor-net

# 启动Prometheus服务
docker run -d --name=prometheus \
  -p 9090:9090 \
  --network=monitor-net \
  -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus

配套的prometheus.yml需要预先配置:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'signalr'
    static_configs:
      - targets: ['signalr-host:5000'] # SignalR服务地址

2.2 在ASP.NET Core中集成监控

首先添加必要的NuGet包:

<PackageReference Include="prometheus-net" Version="6.0.0" />
<PackageReference Include="prometheus-net.AspNetCore" Version="6.0.0" />

然后在Program.cs中注入监控:

// 启用HTTP请求监控
app.UseHttpMetrics();

// 暴露metrics端点
app.MapMetrics();

此时访问/metrics即可看到默认指标。但我们需要定制SignalR专属指标。

三、核心指标采集实战

3.1 连接数监控

在Hub类中维护连接计数器:

using Prometheus;

public class ChatHub : Hub
{
    // 定义连接数指标(Gauge类型适合变化值)
    private static readonly Gauge ActiveConnections = Metrics
        .CreateGauge("signalr_active_connections", "当前活跃连接数");

    public override async Task OnConnectedAsync()
    {
        // 连接建立时+1
        ActiveConnections.Inc();
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        // 连接断开时-1
        ActiveConnections.Dec();
        await base.OnDisconnectedAsync(exception);
    }
}

3.2 消息吞吐量监控

使用Counter统计收发消息量:

private static readonly Counter MessagesReceived = Metrics
    .CreateCounter("signalr_messages_received_total", "累计接收消息数");

private static readonly Counter MessagesSent = Metrics
    .CreateCounter("signalr_messages_sent_total", "累计发送消息数");

public async Task SendMessage(string user, string message)
{
    MessagesReceived.Inc(); // 收到消息+1
    
    // 业务处理逻辑...
    await Clients.All.SendAsync("ReceiveMessage", user, message);
    
    MessagesSent.Inc(); // 发送消息+1
}

3.3 资源占用监控

利用内置的进程指标采集器:

// 在Program.cs中添加
Metrics.SuppressDefaultMetrics();
Metrics.StartDefaultCollector();

这会自动暴露:

  • process_cpu_seconds_total(CPU占用)
  • process_working_set_bytes(内存占用)
  • gc_collection_count(GC回收次数)

四、Grafana可视化与告警

4.1 配置数据源

启动Grafana容器:

docker run -d --name=grafana \
  -p 3000:3000 \
  --network=monitor-net \
  grafana/grafana

在UI中添加Prometheus数据源,地址填写http://prometheus:9090

4.2 制作仪表盘

推荐使用以下Panel配置:

  1. 连接数面板

    • Query: signalr_active_connections
    • Visualization: Stat(显示当前值)
    • Panel Title: "实时连接数"
  2. 消息流量面板

    • Query: rate(signalr_messages_received_total[1m])
    • Visualization: Graph(折线图)
    • Legend: 接收消息速率
  3. 资源面板

    • Query: process_working_set_bytes / 1024 / 1024
    • Unit: MB(内存占用)

4.3 设置阈值告警

在Grafana Alert中配置规则示例:

  • signalr_active_connections > 5000持续5分钟时触发警告
  • process_cpu_seconds_total增长速率 > 50%时触发紧急告警

五、进阶优化技巧

5.1 区分Hub实例指标

当有多个Hub时,建议添加标签区分:

var connections = Metrics
    .CreateGauge("signalr_connections", "各Hub连接数", 
    new GaugeConfiguration
    {
        LabelNames = new[] { "hub_name" }
    });

// 使用时标记Hub名称
connections.WithLabels("chat_hub").Inc();

5.2 监控消息大小分布

使用Histogram统计消息体积:

private static readonly Histogram MessageSizes = Metrics
    .CreateHistogram("signalr_message_bytes",
        buckets: new[] { 128, 512, 1024, 4096 }); // 自定义分桶

public Task Send(byte[] data)
{
    MessageSizes.Observe(data.Length);
    // ...
}

六、避坑指南

  1. 指标命名规范

    • 使用下划线连接单词(signalr_active_connections)
    • 计数器以_total结尾(messages_sent_total)
  2. 性能影响评估

    • 单个Prometheus实例可轻松处理10万级指标
    • 高频更新指标(如每消息都计数)建议使用聚合操作
  3. 采样间隔建议

    • 业务指标:15-30秒采集间隔
    • 系统指标:5-10秒精细监控

七、技术方案对比

监控方案 优点 缺点
Prometheus 云原生集成度高 需要额外维护组件
ApplicationInsights 开箱即用 收费方案成本高
ELK 日志关联分析强 实时性稍差

八、总结

通过本文的实战演示,我们实现了:

  1. 使用prometheus-net库暴露SignalR核心指标
  2. 通过Grafana构建可视化监控看板
  3. 设置业务级告警阈值

建议在生产环境中:

  • 为关键指标设置SLO(如99%消息应在200ms内送达)
  • 定期检查指标基数膨胀问题
  • 结合日志系统进行根因分析