工业全链路数据项目:跨阶段阻塞、时序冲突到架构决策

上周做某冶金行业全流程数据服务项目的第二次验收复查,连轧、锯切两个阶段同时给了「不可验收」的反馈。两个团队各自查了两天日志,都没定位到明确的报错根因。直到我们把两个阶段的错误日志对齐,才发现根源居然出在同一个公共 Mapper 的配置里——这种跨阶段隐性阻塞、时序逻辑打架、字段漏赋值的问题,在涉及多工艺链路的工业数据项目里太典型了。

一处配置,解锁两个卡死阶段

连轧、锯切两阶段的报错表面完全不一样:连轧是工艺数据查询返回列缺失,锯切是判定逻辑拿不到轧机参数。连轧组一开始怀疑数据库表结构变更没同步,锯切组以为是接口参数传输出错,各查各的。合并日志之后才看清,两个阶段的报错都指向同一个公共组件 ProcessSignalSnapshotMapper.xml

这个 Mapper 的 Base_Column_List 节点原本只包含基础业务字段,漏了 11 个工艺核心字段:mill_1mill_8(8 台轧机参数)、double_cut_signal(双剪信号)、sizing_machine_2_low / sizing_machine_3_low(2/3 号轧机低限值)。两个阶段都依赖这个 Mapper 查工艺数据,列一缺,连轧数据组装失败、锯切判定逻辑拿不到参数。

我们只改了这一处配置,补上缺失的 11 列,连轧、锯切两个阶段的阻塞直接解除,验收通过率从 60% 一下提升到 95% 以上。

<!-- 修改前:Base_Column_List缺失11列 -->
<sql id="Base_Column_List">
  select id, batch_no, create_time, ... -- 仅包含基础字段,漏了mill_1~8等工艺字段
</sql>
<!-- 修改后补充缺失列 -->
<sql id="Base_Column_List">
  select id, batch_no, create_time, mill_1, mill_2, ..., mill_8, double_cut_signal, sizing_machine_2_low, sizing_machine_3_low, ... -- 补齐所有工艺字段
</sql>

时序冲突和字段漏赋值,才是更隐蔽的坑

跨阶段配置解决后,阶段三锯切又冒出一个阻断问题:工艺状态 sts=2(待判定状态)时,调用 handleXxxSawing 系列判定方法会直接抛异常。追了三个版本的提交记录才发现,这是状态机流转和判定逻辑的时序冲突——状态走到 sts=2 时,判定方法被上游流程提前触发了,而此时判定逻辑需要的上下文还没初始化完成。

架构师最后选了方案 B:新增一个不校验状态的判定入口,原有逻辑保持不变,新场景走新入口,避免动现有流程。这个决策也避开了大规模重构状态机的风险。

比时序冲突更隐蔽的是字段漏赋值:全项目 5 个核心实体都定义了 is_auto_judged(是否自动判定)字段,但整个项目没有任何地方调用对应的 setter 赋值,字段始终是默认值,自动判定逻辑等于完全失效。最终架构师决策,统一在所有判定逻辑完成后调用 setIsAutoJudged("Y") 赋值,把自动判定链路补全。

// 修复前:5个实体均无setIsAutoJudged调用
FpStepSawing sawing = sawingMapper.selectByBatchNo(batchNo);
// 仅设置业务字段,is_auto_judged始终为默认值null

// 修复后:判定完成后统一赋值
sawing.setIsAutoJudged("Y");
sawingMapper.updateById(sawing);

用户决策,比改代码更需要对齐

这次复查里最核心的几个决策,都来自用户的明确要求。有一条特别关键:「需求是唯一标准,即使和测试库数据不一致也严格遵守需求」。之前开发阶段我们拿测试库的数据对齐过逻辑,结果和用户给的需求文档出现两个 GAP:开坯边沿方向的判断逻辑、锯切开始/完成信号的触发规则。这两个 GAP 后来从 P1 升级成了 P0-6、P0-7,必须改代码对齐需求。

此外用户还明确了几件影响架构的事:炉甩(不合格品剔除)是页面人工操作,自动判定不需要支持,但人工炉甩后必须主动触发 reconcileAll 清理内存队列,优先级从 P0 降为 P1;is_post_segment(是否分段轧制)字段加在 FpStepBlooming(锻坯阶段实体)上,业务上轧后分段属于锻坯属性,自动判定器不赋值,由锯切判定逻辑(SawingJudge)读取该字段判定场景 2;工艺衔接触发规则也调整了——当前工艺结束一支后主动触发后续工艺对账,对账兜底间隔从 10s 缩到 5s,新增了 P1-7、P2-1 优先级任务。

// 修改前:仅被动触发,兜底间隔10s
scheduleService.scheduleReconcile(10, TimeUnit.SECONDS);

// 修改后:主动触发+5s兜底
processEndListener.register(batchNo, () -> {
  // 工艺结束主动触发后续对账
  reconcileService.triggerNextProcessReconcile(batchNo);
  // 兜底间隔缩短为5s
  scheduleService.scheduleReconcile(5, TimeUnit.SECONDS);
});

这次复查前后花了 3 天,解决了 4 个 P0 级阻塞,四阶段验收通过率从平均 65% 提到了 92%。回头看,几个教训很实在:多阶段项目先拉通所有阶段的错误日志查公共依赖,别陷在各自阶段的局部逻辑里,这次跨阶段阻塞要是开头就对日志,至少省两天;时序冲突优先新增入口、加功能开关做分支隔离,别直接改现有校验规则;任何和需求文档不一致的逻辑,哪怕测试数据能跑通也得改,工业链路的逻辑错误会直接带偏真实生产数据;上线前一定要扫一遍实体字段的赋值链路,避免出现"字段定义了却永远不赋值"的坑。

posted @ 2026-09-15 07:08  钱栈up  阅读(5)  评论(0)    收藏  举报