一、为什么需要监控SignalR服务端性能
SignalR作为.NET生态下优秀的实时通信框架,在在线聊天、实时游戏、金融行情推送等场景中广泛应用。但随着连接数增长,服务端可能面临连接数暴增、消息积压、CPU/内存飙升等问题。想象一下,当你的在线教育平台突然涌入上万学生时,若无法实时掌握服务端状态,系统可能毫无征兆地崩溃。
典型问题场景:
- 连接数超过服务器承载上限导致拒绝服务
- 消息吞吐量突增引发线程池饥饿
- 内存泄漏使服务间歇性卡顿
通过Prometheus+Grafana这套云原生监控组合拳,我们可以像给SignalR装上"心电图仪",实时捕捉以下关键指标:
- 当前活跃连接数(反映服务负载)
- 消息收发速率(衡量处理能力)
- 内存/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配置:
连接数面板
- Query:
signalr_active_connections - Visualization: Stat(显示当前值)
- Panel Title: "实时连接数"
- Query:
消息流量面板
- Query:
rate(signalr_messages_received_total[1m]) - Visualization: Graph(折线图)
- Legend: 接收消息速率
- Query:
资源面板
- Query:
process_working_set_bytes / 1024 / 1024 - Unit: MB(内存占用)
- Query:
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);
// ...
}
六、避坑指南
指标命名规范
- 使用下划线连接单词(signalr_active_connections)
- 计数器以
_total结尾(messages_sent_total)
性能影响评估
- 单个Prometheus实例可轻松处理10万级指标
- 高频更新指标(如每消息都计数)建议使用聚合操作
采样间隔建议
- 业务指标:15-30秒采集间隔
- 系统指标:5-10秒精细监控
七、技术方案对比
| 监控方案 | 优点 | 缺点 |
|---|---|---|
| Prometheus | 云原生集成度高 | 需要额外维护组件 |
| ApplicationInsights | 开箱即用 | 收费方案成本高 |
| ELK | 日志关联分析强 | 实时性稍差 |
八、总结
通过本文的实战演示,我们实现了:
- 使用prometheus-net库暴露SignalR核心指标
- 通过Grafana构建可视化监控看板
- 设置业务级告警阈值
建议在生产环境中:
- 为关键指标设置SLO(如99%消息应在200ms内送达)
- 定期检查指标基数膨胀问题
- 结合日志系统进行根因分析
评论