2. 看板架构基础:前后端分离架构、数据流模型、组件化设计原则

工程分析平台的看板模块,其架构设计直接决定了数据刷新效率与后续性能优化的空间。本章从三个核心维度展开:前后端分离架构、单向数据流模型以及组件化设计原则。理解这些基础,是后续实现增量更新、虚拟滚动与缓存策略的前提。

2.1 前后端分离架构

现代看板系统普遍采用前后端分离架构,将视图渲染与数据逻辑解耦。前端负责看板布局、图表渲染与用户交互;后端专注数据聚合、清洗与推送。这种分离带来了明确的职责边界与独立的扩展能力。

层次 职责 典型技术栈 性能关注点
前端层 看板布局、图表渲染、交互响应、本地缓存 React / Vue + ECharts / D3.js DOM 更新频率、虚拟滚动、组件卸载与复用
网关层 请求路由、鉴权、限流、协议转换 Nginx / Kong / Envoy 连接池复用、请求合并、超时控制
后端层 数据聚合、业务逻辑、缓存策略、推送服务 Spring Boot / Go + Redis / WebSocket 查询优化、缓存命中率、推送频率控制
数据层 时序数据存储、元数据管理、历史归档 InfluxDB / ClickHouse / PostgreSQL 分区裁剪、预聚合、TTL 策略
架构要点:前后端通过 RESTful API 或 WebSocket 通信。对于实时看板,推荐使用 WebSocket 建立长连接,避免 HTTP 轮询带来的头部开销与连接建立延迟。
前后端分离看板架构 前后端分离看板架构 前端层 看板布局 / 图表渲染 交互响应 / 本地缓存 网关层 路由 / 鉴权 / 限流 协议转换 / 请求合并 后端层 数据聚合 / 业务逻辑 缓存 / WebSocket 推送 数据层 时序数据库 / 元数据 历史归档 / TTL 策略 通信协议:REST / WebSocket 数据格式:JSON / Protobuf

2.2 单向数据流模型

看板的数据流遵循 单向数据流 原则:数据从后端流向状态管理容器,再流向视图组件;用户交互产生的动作反向触发数据请求,形成闭环。这种模型保证了数据变更的可预测性与可追踪性。

数据流核心阶段

  1. 数据采集与聚合:后端从数据层拉取原始指标,执行聚合计算(如平均值、百分位、同比环比),生成看板所需的结构化数据集。
  2. 推送与分发:通过 WebSocket 或 Server-Sent Events (SSE) 将增量数据推送到前端;前端网关层可对高频推送做 节流(throttle) 或 防抖(debounce) 处理。
  3. 状态管理:前端状态容器(如 Redux、Pinia、Zustand)接收数据,执行浅比较或不可变更新,仅触发受影响的组件重渲染。
  4. 视图渲染:组件从状态中读取切片数据,驱动图表库(ECharts / D3.js)更新 SVG 或 Canvas 画布。
性能关键点:单向数据流中,状态更新的粒度直接影响渲染性能。建议将看板拆分为多个独立的状态切片(如“温度指标切片”、“压力指标切片”),避免单个状态树过大导致全量 diff。
看板单向数据流模型 看板单向数据流模型 数据源 时序库 / 消息队列 后端聚合 预计算 / 缓存 推送服务 WebSocket / SSE 状态管理 Redux / Pinia 视图组件 图表 / 表格 / 卡片 用户动作(反向触发) 数据流方向:单向闭环 状态更新粒度:按切片隔离

2.3 组件化设计原则

看板由多个可视化卡片(Widget)组成,每个卡片应视为一个独立组件。组件化设计遵循以下原则,以支撑高性能刷新与灵活布局。

核心原则

  • 单一职责:每个组件只负责一种数据类型的展示(如“实时温度曲线”组件不混入“历史压力表格”逻辑),便于独立测试与性能优化。
  • 可复用性:通过 props / slots 暴露配置项(如刷新间隔、数据源 ID、图表类型),使同一组件可在不同看板页面复用。
  • 生命周期管理:组件挂载时建立 WebSocket 订阅或轮询定时器;卸载时主动清理连接与定时器,防止内存泄漏与无效请求。
  • 虚拟化支持:当看板包含大量卡片时,仅渲染视口内的组件(虚拟滚动),未进入视口的组件暂停数据订阅。

组件层级示例

层级 组件名称 职责 性能关注点
容器层 DashboardContainer 管理看板布局、全局刷新策略、组件注册 布局重排开销、组件懒加载
卡片层 MetricCard 封装单个指标卡片的标题、数值、趋势箭头 数值动画性能、条件渲染
图表层 TimeSeriesChart 渲染时序曲线图,支持增量追加数据点 Canvas 复用、数据点裁剪
数据层 useMetricData 自定义 Hook,封装数据订阅、缓存、重试逻辑 订阅去重、缓存失效策略
常见陷阱:避免在组件内部直接发起 HTTP 请求。应将数据获取逻辑提升到容器层或自定义 Hook 中,通过 props 向下传递数据。这样当刷新策略变更时,只需修改容器层,无需改动每个卡片组件。

组件通信模式

看板组件间推荐使用 发布-订阅 模式或 状态管理库 进行通信,避免多层 props 透传。例如,当用户切换全局时间范围时,容器层发布事件,各卡片组件订阅后重新请求数据。

// 示例:使用发布-订阅模式管理看板刷新事件
class RefreshBus {
  constructor() {
    this.subscribers = new Map();
  }

  subscribe(widgetId, callback) {
    if (!this.subscribers.has(widgetId)) {
      this.subscribers.set(widgetId, []);
    }
    this.subscribers.get(widgetId).push(callback);
  }

  publish(widgetId, payload) {
    const callbacks = this.subscribers.get(widgetId);
    if (callbacks) {
      callbacks.forEach(cb => cb(payload));
    }
  }

  unsubscribe(widgetId) {
    this.subscribers.delete(widgetId);
  }
}

// 使用示例
const bus = new RefreshBus();
bus.subscribe('temp-chart', (data) => updateChart(data));
bus.publish('temp-chart', { timestamp: Date.now(), value: 85.3 });
设计建议:为每个看板组件定义 刷新策略接口(如 refreshInterval、retryCount、cacheTTL),通过配置文件或后端下发的元数据驱动,避免硬编码刷新逻辑。