4. 高可用架构设计原则
EAP(Equipment Automation Program,设备自动化程序)位于 MES 与生产设备之间,向上承接工单、配方、物料与工艺指令,向下通过 SECS/GEM、OPC UA、Modbus TCP 等协议与机台交互。它既是数据通道,也是控制通道,一旦中断,轻则数据补录,重则整条产线停线。因此,EAP 的高可用不能只靠“多部署一个进程”,而应把五条设计原则落到具体的进程、连接、状态与接口上。
一、冗余:消除单点,但要区分“热”与“冷”
冗余的目标是让任一单点失效时系统仍可服务。EAP 中常见的单点包括:EAP 服务实例、SECS/GEM 连接、消息中间件、数据库、以及 MES 接口。落地时通常采用“双实例 + 主备切换”或“多实例 + 负载分担”。
以某 8 寸晶圆厂 EAP 为例,同一台设备由两个 EAP 实例管理,通过共享的注册中心(如 etcd 或 ZooKeeper)竞争设备锁:持有锁的实例为 Active,负责与机台建立 SECS 连接并收发消息;另一实例为 Standby,只保持心跳与状态同步。当 Active 心跳超时(示例阈值:3 次心跳、每次 2 秒),Standby 在 1 秒内抢锁并接管。这里的关键参数是“切换窗口”,必须小于机台侧 SECS 的 T3 超时(通常 45 秒),否则机台会判定通信中断并报警。
冗余不是越多越好。双实例已能覆盖绝大多数单点故障,若盲目扩到四实例,反而增加锁竞争与状态同步开销。冗余的粒度应精确到“故障域”:同一机台的两个 EAP 实例应部署在不同物理机或不同可用区,避免同一台宿主机宕机导致双实例同时失效。
二、故障隔离:把爆炸半径限制在单台设备
故障隔离的核心是“一个设备的问题不拖垮整个 EAP”。常见做法有三层:
- 进程隔离:每台设备对应独立的连接工作线程或协程,单设备的消息积压不阻塞其他设备。
- 资源隔离:为每个设备连接设置独立的发送队列与内存上限,例如单设备队列上限 5000 条,超过则触发背压而非无限堆积。
- 依赖隔离:MES 接口调用使用独立线程池与熔断器,当 MES 响应时间超过 2 秒时快速失败,避免 EAP 线程被拖死。
一个典型的隔离失效场景是:某台设备的 SECS 消息解析异常导致线程死循环,若所有设备共用同一线程池,其他设备的消息也会被阻塞。因此,EAP 应按设备维度划分执行单元,并在监控中按设备维度统计队列深度、处理时延与错误率,使故障定位能直接落到具体机台。
三、优雅降级:断线时保留核心能力
优雅降级指系统在部分依赖不可用时,仍能提供有限但关键的服务。EAP 的降级策略通常按“数据重要性”分层:
| 依赖故障 | 降级动作 | 保留能力 |
|---|---|---|
| MES 不可达 | 本地缓存工单与配方,消息写入本地队列 | 设备继续按已下发配方生产,数据待恢复后补传 |
| 数据库不可写 | 切换为本地文件或内存队列暂存 | SECS 通信不中断,事件不丢失 |
| 消息中间件不可达 | 启用本地磁盘缓冲,限制缓冲上限 | 短时间内的数据不丢,超限后告警 |
降级必须有明确的“恢复条件”和“数据回补机制”。例如 MES 恢复后,EAP 按时间顺序重放本地队列,并对每条消息携带唯一序列号,MES 侧按序列号去重,避免重复入库。降级期间应持续告警,而不是静默吞掉异常。
四、幂等设计:让重试与重放安全
EAP 与 MES、设备之间的消息可能因超时、重连、切换而重复发送。幂等设计保证同一业务操作执行多次与执行一次结果一致。落地方式是为每条关键消息生成全局唯一 ID(如“设备号 + 事件类型 + 时间戳 + 序列号”),并在接收端维护去重表。
消息ID示例:EQP-08-001|LOT_START|20240521T103015|000123
去重表结构(示例):
msg_id VARCHAR(128) PRIMARY KEY
biz_type VARCHAR(32)
created_at DATETIME
expire_at DATETIME -- 例如保留 24 小时
对于设备侧指令,幂等还体现在“重复下发不产生副作用”。例如重复下发“开始加工”指令时,EAP 应先查询设备当前状态,若已处于加工中则直接返回成功,而不是再次触发。对于 MES 侧的数据上报,接收端按 msg_id 做插入或忽略,保证同一事件只入库一次。
五、状态外置:让实例无状态、可随时接管
状态外置是把 EAP 实例内的会话状态、设备状态、队列状态从进程内存迁移到外部共享存储(如 Redis、数据库、分布式队列)。这样任一实例崩溃后,另一实例可直接读取共享状态继续工作,而不需要从设备重新同步全部上下文。
需要外置的典型状态包括:设备当前控制状态(Online/Offline)、当前工单与配方版本、SECS 会话的 T3/T5/T6/T7 定时器上下文、未确认的消息序列号、以及本地缓冲队列。外置后,EAP 实例本身可以做到“无状态”,从而支持滚动升级、快速重启和跨主机迁移。
需要注意的是,状态外置会引入外部存储的可用性依赖。因此共享存储本身也必须冗余,例如 Redis 采用主从 + 哨兵,数据库采用主备。同时,状态写入应尽量批量、异步,避免每条消息都同步写外部存储而拖慢 SECS 响应。
六、五条原则的协同关系
这五条原则不是并列的清单,而是相互支撑的整体。冗余提供实例级容错,故障隔离限制单设备影响范围,优雅降级保证依赖故障时核心功能可用,幂等设计让重试与切换后的重放安全,状态外置则让冗余切换和降级恢复成为可能。缺少状态外置,Standby 实例无法快速接管;缺少幂等,切换后的消息重放会造成重复工单或重复入库;缺少隔离,一台设备的异常会同时击穿冗余与降级策略。
在 EAP 的实际落地中,建议按“先隔离、再外置、后冗余”的顺序推进:先把设备连接与线程池隔离,再把会话与队列状态外置到共享存储,最后引入双实例与自动切换。每引入一层,都要配套监控指标与演练方案,例如定期执行主备切换演练、模拟 MES 不可达验证降级回补、注入重复消息验证幂等去重。只有经过验证的高可用,才是真正可用的高可用。