系统设计:实时监控大盘
需求假设
- 展示几十个指标和多张图表。
- 秒级更新,允许短暂断线但不能无限丢数据。
- 支持时间范围、筛选、下钻和大屏模式。
- 长时间运行不能持续增长内存。
总体架构
初始历史数据走 HTTP,增量数据走 WebSocket 或 SSE。这样比让实时通道承担所有查询更容易缓存、分页和恢复。
WebSocket 还是 SSE
- 只需要服务端推送、希望自动重连:优先考虑 SSE。
- 需要高频双向通信或二进制数据:考虑 WebSocket。
- 更新频率较低且基础设施简单:轮询可能是性价比最高的方案。
选择要结合代理超时、连接数限制、鉴权和运维能力。
数据更新策略
不要每收到一条消息就立即让所有图表渲染:
- 消息进入内存缓冲区。
- 按指标 ID 合并同一时间窗口内的数据。
- 每 100~500ms 批量提交一次状态更新。
- 图表只保留可见时间窗口和有限历史点。
高频计算可放入 Worker,主线程只接收适合渲染的聚合结果。
一致性与断线恢复
- 消息携带递增序号或时间戳。
- 客户端记录最后成功处理的位置。
- 重连后请求缺失区间或重新拉取快照。
- 发现序号跳跃时不要假装数据完整。
- 使用指数退避并加入随机抖动,避免集体重连风暴。
性能与稳定性
- 图表组件按数据域拆分,避免全局状态更新导致全部重绘。
- 页面不可见时降低更新频率。
- 限制数据点、消息队列和日志容量。
- 对慢接口、连接状态、消息积压和渲染耗时设置指标。
- 数据源异常时显示“最后更新时间”和数据陈旧状态。
高频追问
- 十张图表同时更新为什么卡?
- 页面放置一整天后内存越来越高如何定位?
- WebSocket 断线期间的数据如何补齐?
- 服务端突发每秒一万条消息时客户端如何保护自己?