如何在Blazor Server应用中正确统计SignalR消息的数量与大小
统计Blazor Server下SignalR消息量的正确方法
以下方案从准确性从高到低排序,可按需选择:
1. 使用内置诊断监听器(最推荐,无误差)
ASP.NET Core自带的DiagnosticListener机制可以直接捕获所有SignalR的收发事件,不需要解析日志,完全贴合实际消息流转逻辑,还可以直接对齐Azure SignalR的计费规则。
首先实现两个观察者类:
public class SignalRMessageObserver : IObserver<DiagnosticListener> { public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(DiagnosticListener listener) { if (listener.Name == "Microsoft.AspNetCore.SignalR") { listener.Subscribe(new SignalREventObserver()); } } } public class SignalREventObserver : IObserver<KeyValuePair<string, object>> { // 可根据需求替换为写入日志、时序数据库等逻辑 public static long TotalSentMessages = 0; public static long TotalReceivedMessages = 0; public static long TotalSentBytes = 0; public static long TotalReceivedBytes = 0; public static long TotalBillingUnits = 0; public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(KeyValuePair<string, object> evt) { switch (evt.Key) { case "Microsoft.AspNetCore.SignalR.ReceivedMessage": dynamic payload = evt.Value; var msgLength = payload.Message.Length; TotalReceivedMessages++; TotalReceivedBytes += msgLength; // *适配Azure计费规则:每2KB计算为1个计费单位* TotalBillingUnits += (long)Math.Ceiling((double)msgLength / 2048); break; case "Microsoft.AspNetCore.SignalR.SentMessage": dynamic payload = evt.Value; var msgLength = payload.Message.Length; TotalSentMessages++; TotalSentBytes += msgLength; TotalBillingUnits += (long)Math.Ceiling((double)msgLength / 2048); break; } } }
然后在Program.cs的配置管道末尾注册监听器即可生效:
DiagnosticListener.AllListeners.Subscribe(new SignalRMessageObserver());
你可以自行扩展按时间窗口统计、按消息类型拆分统计的逻辑,精准定位高消耗的消息来源。
2. 使用Azure SignalR自带指标
如果已经接入Azure SignalR服务,可以直接在Azure门户对应SignalR资源的【指标】面板查看官方统计数据,包含总消息数、出入站字节数、计费单位数等维度,数据和实际账单完全一致,无需自行开发。
3. 优化日志解析方案
如果坚持使用日志解析的方式,建议改为结构化日志输出(比如使用Serilog输出JSON格式日志),直接提取消息大小字段,不需要用正则匹配,准确率会大幅提升。
Blazor Server场景的高消息量优化建议
你遇到的超高消息消耗绝大多数是Blazor默认渲染逻辑导致的,可针对性优化:
- 拖拽等高频率UI事件,添加
@on{mousemove}:preventDefault、@on{mousemove}:stopPropagation特性减少不必要的回传 - 大体积初始数据不要走Blazor渲染通道传输,改用前端直接调用接口拉取,绕过SignalR
- 组件层面重写
ShouldRender方法,减少非必要的渲染触发,降低OnRenderCompleted类消息的发送量 - 高频事件可添加防抖节流逻辑,合并多条消息为一条提交
内容的提问来源于stack exchange,提问作者Giancarlo Sierra
相关产品推荐
相关产品推荐

