系统设计:实时监控大盘

需求假设

  • 展示几十个指标和多张图表。
  • 秒级更新,允许短暂断线但不能无限丢数据。
  • 支持时间范围、筛选、下钻和大屏模式。
  • 长时间运行不能持续增长内存。

总体架构

初始历史数据走 HTTP,增量数据走 WebSocket 或 SSE。这样比让实时通道承担所有查询更容易缓存、分页和恢复。

WebSocket 还是 SSE

  • 只需要服务端推送、希望自动重连:优先考虑 SSE。
  • 需要高频双向通信或二进制数据:考虑 WebSocket。
  • 更新频率较低且基础设施简单:轮询可能是性价比最高的方案。

选择要结合代理超时、连接数限制、鉴权和运维能力。

数据更新策略

不要每收到一条消息就立即让所有图表渲染:

  1. 消息进入内存缓冲区。
  2. 按指标 ID 合并同一时间窗口内的数据。
  3. 每 100~500ms 批量提交一次状态更新。
  4. 图表只保留可见时间窗口和有限历史点。

高频计算可放入 Worker,主线程只接收适合渲染的聚合结果。

一致性与断线恢复

  • 消息携带递增序号或时间戳。
  • 客户端记录最后成功处理的位置。
  • 重连后请求缺失区间或重新拉取快照。
  • 发现序号跳跃时不要假装数据完整。
  • 使用指数退避并加入随机抖动,避免集体重连风暴。

性能与稳定性

  • 图表组件按数据域拆分,避免全局状态更新导致全部重绘。
  • 页面不可见时降低更新频率。
  • 限制数据点、消息队列和日志容量。
  • 对慢接口、连接状态、消息积压和渲染耗时设置指标。
  • 数据源异常时显示“最后更新时间”和数据陈旧状态。

高频追问

  • 十张图表同时更新为什么卡?
  • 页面放置一整天后内存越来越高如何定位?
  • WebSocket 断线期间的数据如何补齐?
  • 服务端突发每秒一万条消息时客户端如何保护自己?