3. 平台集成总体架构设计

实验数据质量平台不是一个单体应用,它需要同时对接LIMS、ELN、仪器采集网关、数据湖、规则引擎和报表服务。总体架构设计的核心任务,是把“谁负责什么、数据怎么走、控制怎么下发、边界在哪里、契约怎么定、未来怎么扩”这六个问题在图纸上一次性说清楚。本节围绕一张分层架构图展开,逐层说明数据流与控制流的走向,并给出接口契约与可扩展性的落地方法。

一、分层架构:五层职责与依赖方向

推荐采用五层结构,自上而下为:接入层、服务层、领域层、数据层、基础设施层。依赖方向严格自上而下,禁止反向调用,跨层访问通过接口而非直接引用实现。

  • 接入层:面向Web控制台、OpenAPI网关、消息订阅端,负责鉴权、限流、协议转换(HTTP/HTTPS、MQTT、gRPC)。
  • 服务层:编排用例,如“提交一批检测数据并触发质量校验”,本身不写业务规则,只做流程编排与事务边界。
  • 领域层:质量规则、异常判定、数据血缘、版本快照等核心逻辑所在,是平台最稳定的部分。
  • 数据层:原始数据区、清洗区、质量结果区、元数据与规则库,按冷热分离存储。
  • 基础设施层:消息队列、对象存储、调度器、日志与指标采集。

分层的价值在于:当仪器协议从Modbus换成OPC UA时,只改接入层的适配器;当质量规则从“3σ”升级为“MAD+趋势”时,只改领域层。层与层之间通过明确定义的接口通信,任何一层内部实现变化不应波及其他层。

二、数据流与控制流:两条主线

数据流是“自下而上”的:仪器/系统产生原始记录 → 接入层归一化 → 服务层编排 → 领域层校验 → 数据层落库 → 报表/告警输出。控制流是“自上而下”的:用户在控制台配置规则或触发重跑 → 服务层接收指令 → 领域层加载规则 → 调度器向采集端下发任务 → 采集端回传执行状态。

两条流必须解耦。数据流走消息队列做削峰填谷,控制流走独立的命令通道并带确认机制。若把控制指令混入数据队列,一旦数据积压,规则重跑指令会被延迟数分钟甚至更久,排障时难以区分“没执行”和“执行了但没回传”。

实验数据质量平台分层架构与数据/控制双流 接入层 Web控制台 OpenAPI网关 MQTT/OPC UA 消息订阅端 服务层 用例编排 / 事务边界 鉴权 / 限流 / 审计 任务调度与状态回传 领域层 质量规则引擎 异常判定 / 分级 数据血缘 版本快照 数据层 原始数据区 清洗区 质量结果区 元数据/规则库 基础设施层 消息队列 对象存储 调度器 日志/指标 数据流(自下而上) 控制流(自上而下) 服务边界与契约要点 接入层↔服务层:REST/gRPC,契约含鉴权头、幂等键、超时与重试策略;服务层↔领域层:进程内接口,禁止跨层直连数据库;领域层↔数据层:Repository接口,屏蔽存储差异。

三、服务边界:按“变化频率”切分

服务边界不应按组织架构或数据库表来切,而应按“变化频率”和“数据所有权”来切。建议划分四个核心服务:

  • 采集接入服务:负责协议适配与原始数据落库,变化频率高(仪器型号多),独立部署。
  • 质量校验服务:承载规则引擎与异常判定,变化频率中(规则迭代),是平台核心。
  • 元数据服务:管理字段定义、单位、量纲、规则版本,变化频率低但被广泛依赖。
  • 查询报表服务:只读,面向大屏与导出,可独立扩容。

边界清晰后,每个服务拥有自己的数据表,禁止跨服务直接查库。质量校验服务需要元数据时,通过元数据服务提供的接口获取,并做本地缓存,缓存失效时间建议设为5分钟,规则版本变更时主动推送失效通知。

四、接口契约:三个必须写死的字段

接口契约是集成工程中最容易埋雷的地方。无论采用REST还是gRPC,以下三个字段必须在契约中明确:

  1. 幂等键(idempotency_key):由调用方生成,服务端在24小时内对相同键去重。仪器网络抖动导致重复上报时,避免同一批数据被校验两次。
  2. 数据版本(schema_version):标明本次载荷遵循的字段定义版本。当元数据服务升级字段时,旧版本客户端仍可提交,由服务端做兼容映射。
  3. 追踪ID(trace_id):贯穿接入、校验、落库、告警全链路,排障时用它在日志中串联一次请求的完整路径。

以下是一个提交质量校验任务的请求契约示例(JSON over HTTPS):

POST /api/v1/quality/validate
Headers:
  Authorization: Bearer <token>
  X-Idempotency-Key: 7f3a9c21-4b8e-4d0a-9f1e-2c5b8d6a0e33
  X-Trace-Id: trace-20240612-000871
Body:
{
  "schema_version": "1.4",
  "batch_id": "BATCH-20240612-009",
  "instrument_id": "HPLC-03",
  "records": [
    {"sample_id": "S-1024", "value": 98.72, "unit": "mg/L", "ts": "2024-06-12T09:15:03+08:00"},
    {"sample_id": "S-1025", "value": 101.05, "unit": "mg/L", "ts": "2024-06-12T09:15:07+08:00"}
  ]
}
Response 202:
{
  "task_id": "TASK-9f2c1a",
  "status": "accepted",
  "trace_id": "trace-20240612-000871"
}

注意响应返回202而非200,表示任务已受理但尚未完成校验。调用方应通过GET /api/v1/quality/tasks/{task_id}轮询或订阅回调获取最终结果。这种异步契约设计,使校验服务在规则复杂、单批数据量大时不会阻塞接入层。

五、可扩展性设计:三个预留点

可扩展性不是“以后再说”,而是在架构中预留明确的扩展点:

  • 规则插件化:规则引擎采用“规则描述 + 执行器”分离。新增一条“相邻批次偏差超过15%告警”的规则,只需注册新的规则描述与执行器,不改动校验主流程。
  • 协议适配器热插拔:接入层定义统一的ProtocolAdapter接口,包含connect()、readBatch()、ack()三个方法。新增一种仪器协议时,实现该接口并注册到适配器工厂即可。
  • 存储分层可替换:数据层通过Repository接口暴露读写能力。当前原始数据写入对象存储,若未来需要迁移到时序数据库,只需替换Repository实现,领域层无感知。
判断扩展点是否有效的简单方法:假设明天要接入一种全新仪器、新增一类质量规则、更换一种存储引擎,分别需要改动几个服务?如果答案都是“一个”,说明边界和扩展点设计到位;如果需要改动三个以上,说明耦合仍然过重。

六、落地检查:架构评审的五个问题

在架构评审会上,用以下五个问题快速检验设计质量:数据从仪器到质量结果,经过哪几个服务、每段延迟预算是多少?控制指令下发后,如何确认执行端已收到并开始执行?某个服务宕机时,数据是丢失、堆积还是降级?接口契约中幂等键、版本号、追踪ID是否齐全?新增一条规则或一种协议,改动范围是否控制在一个服务内?这五个问题答不清楚,架构图就还停留在“画得好看”的阶段,无法支撑后续30个章节中反复出现的集成、排障与优化工作。