多协议工业采集系统:配置模型与运行链路的架构设计

接入设备不只是调用一次协议库。连接参数如何复用,点位怎样映射到业务字段,慢设备和失败的下游如何影响采集,决定了系统能否继续扩展。本文以我开发的工业采集系统为例,解释这些边界如何划分,以及当前实现还存在哪些限制。

更新于 2026-09-09。依据当前项目源码与实现文档整理;运行范围见文末,不将模拟器演练等同于工业现场验收。

从三个问题建立配置模型

最初可以把 IP、寄存器地址、字段名和存储参数放进一份设备配置。设备少时简单,但当一台 PLC 对应多个工位、同类产品来自不同协议时,重复参数和隐式关联开始增加。

我把配置分为三个实体:

实体 回答的问题 主要内容
Connection 如何建立连接 协议、地址、端口及协议专属参数
Template 如何取得并解释数据 连接引用、点位、读取方式、缩放、采集功能
Product 数据按什么模型组织 属性名、类型、单位、标签与存储定义

引用由模板发起:Template.deviceId → Connection,Template.productKey → Product。它们不是三级继承关系。

Connection                         Product
协议与连接参数                     业务字段与标签
        ↑ deviceId             ↑ productKey
        └──────── Template ────┘
                  点位与采集规则

例如,温度工位和压力工位可以引用同一个连接,但有不同采集周期和点位。两个采用不同协议的模板,也可以把读到的数据映射为相同的 temperature 业务属性。

这降低了配置重复,但没有消除契约成本:模板点位名必须与产品属性名对齐。修改名称不仅是改显示文本,还可能改变存储映射和历史查询。未匹配字段的处理应按具体存储后端检查,不能把所有后端都概括为“自动兜底且可查询”。

统一运行链路,而不是抹平协议差异

系统支持 S7、MC、Modbus、OPC UA 四类协议。Session 层封装连接与读写,配置化 Handler 负责将模板转换为相应的协议请求。

统一的是上层使用方式。S7 的地址、Modbus 的寄存器类型与字节序、OPC UA 的 NodeId 和安全连接要求仍然不同。新增协议不仅需要实现 read,还要核对连接生命周期、批量读取、类型转换、写入与错误分类。

按当前 BaseDeviceHandler.collect(),主要步骤是:

启用检查 → 触发条件 → 可选读前复位
  → readData → buildEntity → processAfterRead
  → checkRules
  → 可选转发 → 可选存储 → 可选读后复位
  → 计数与日志 → 更新数据缓存 → 发布采集结果事件

这段顺序比“协议差异只在一个读取步骤”更准确:读前后动作、解码和异常处理也可能受到协议影响。规则检查位于转发和存储之前,因此规则动作的耗时值得纳入采集延迟分析。

我保留了硬编码 Handler 与模板 Handler 两种入口。常规接入优先通过配置完成;特殊行为可以写代码实现。代价是两条入口都需要遵守共同的事件和数据契约,不能只测试模板路径。

调度与执行分离解决了什么

plcScheduler 定时投递任务,plcExecutor 执行实际采集。这样,调度线程不用等待设备 I/O 完成。MQTT 发布另有执行池,存储也有相应的异步处理链路。

但执行池是共享资源。一台慢设备不会直接占住调度线程,仍可能占住执行线程;大量慢请求会使队列积压。固定频率投递也不自动保证同一设备串行执行。

判断隔离是否有效,应同时观察:

观察对象 要回答的问题
队列长度与排队时间 新一轮采集是否已经落后于配置周期
单次采集耗时 慢在读取、规则、存储提交还是其他步骤
同设备并发 上一轮未完成时,下一轮是否允许进入
拒绝与丢弃 任务过载时跳过、排队还是调用线程执行

针对具体规模,可以进一步采用单设备串行、跳过重叠轮次或独立执行配额;这些需要依据实时性要求选择,不能仅靠增加线程数解决。

重连是独立的生命周期

当前设计结合采集异常与连接巡检发现断线,通过 reconnectTasks 避免重复安排重连任务,并使用首次快速重试、后续指数退避的策略。

退避解决的是请求节奏,不等于已经恢复业务。连接建立后,还要确认读请求成功、点位有效,以及旧任务没有继续操作旧 Session。连接正常、采集成功、数据已存储是三个不同状态。

因此,监控界面不应只显示一个“在线”圆点。连接状态用于定位链路问题,采集结果用于判断数据是否可用,存储与发布结果应来自各自的完成事件。

双配置源服务不同的维护方式

YAML 适合配置随版本审查和部署,数据库配置适合页面编辑。通过配置源接口与条件装配,两者复用运行逻辑;文件模式限制配置写入,数据库模式提供 CRUD。

这是维护方式的选择,不是“演示切换成生产”的开关。数据库模式仍需要考虑配置校验、修改权限、并发更新、热重载失败和审计;YAML 也可以用于经过管理的正式部署。

另一个细节是参数继承:模板未显式设置的连接参数应在解析时继承,而不是在保存时把继承值固化为覆盖值。否则,随后修改 Connection,模板看起来引用它,实际却不再跟随。

为什么没有直接拆成微服务

当前规模下,模块边界比进程数量更重要。将协议采集、配置、规则和存储保留在一个应用中,部署和调试成本较低,也便于用模拟器验证整条软件链路。

代价是故障和资源竞争仍可能跨模块传播。独立 AI 平台的拆分有更具体的理由:它需要连接多个业务系统、独立管理模型和工具,生命周期已经不同。详细结构见AI 平台架构。

实现依据与验证范围

主要实现入口是 DeviceManager、BaseDeviceHandler、协议 Session、DeviceTemplateConfig 和配置源接口。2026-09-07 的运行记录确认了 Modbus、OPC UA 模拟来源的采集、部分 MySQL 历史和 WS 事件;该记录不覆盖 S7/MC 现场兼容性、全部告警联动与长稳性能。

这个架构最值得复用的是配置职责与运行职责的分开,以及对各阶段结果的独立表达。继续阅读数据生命周期、规则引擎和项目全景,可以看到这些边界如何延伸到具体功能。