ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

EAP状态持久化策略探索

EAP状态持久化策略探索 EAP状态持久化策略探索在之前的优化中我们将EAP启动状态section/zone是否已启动从Dictionarystring, bool升级为线程安全的EapSectionStateManager基于HashSetstring lock。当前实现是纯内存in-memory程序重启后所有状态重置为“未启动”。现在我们系统性地探索持久化Persistence策略目标是让EAP状态在应用崩溃、重启、服务器重启等场景下可恢复同时兼顾工业控制系统的安全性、实时性、简洁性。1. 为什么需要持久化业务场景分析当前痛点如果EAP主机Host异常重启正在“已启动”状态的section会被重置导致下次S2F41 START消息可能重复触发RemoteCallStartFlow或丢失流程状态。GEM/SECS标准参考SEMI E30GEM明确要求Control StateOnline/Offline/Remote/Local等关键状态必须保存在非易失性存储non-volatile storage中重启后状态应保持一致。EAP特有场景您的EapSectionStateManager是自定义的“远程启动标记”并非标准GEM状态。因此持久化不是强制但能显著提升系统鲁棒性尤其在24×7产线环境中。潜在风险持久化后需考虑“状态过期”e.g. 产线重启后是否强制清零、数据一致性、文件/DB损坏恢复。结论推荐轻量级持久化而不是完全不持久化。优先确保“安全重启”。2. 常见持久化策略对比适合工业EAP/.NET环境策略实现复杂度性能/实时性可靠性适用场景优缺点总结1. 纯内存当前★☆☆☆☆极高低重启丢失测试/简单场景简单但不满足产线高可用要求2. JSON文件持久化最推荐★★☆☆☆高1ms中高原子写备份多数EAP系统10~100个section轻量、无依赖、易部署。工业中最常用3. SQLite单文件数据库★★★☆☆高高事务ACID需要审计/历史记录支持并发、查询灵活。体积稍大4. 企业级数据库SQL Server/PostgreSQL★★★★☆中极高已集成MES/CIM的大厂强大但运维成本高5. Event Sourcing事件溯源★★★★★中极高需要完整审计轨迹高级方案可回放任意时刻状态6. Redis/分布式缓存★★★☆☆极高高需集群多主机/分布式EAP适合云化/多实例成本较高工业控制最佳实践基于SECS/GEM社区经验优先JSON文件无需额外服务部署简单符合半导体EAP“轻量化”原则。必须原子写写临时文件 → 重命名防止半途崩溃导致文件损坏。启动时加载 校验损坏时自动回退为空状态安全优先。周期性或变更时 程序退出时保存。3. 推荐方案JSON文件持久化完整实现3.1 核心设计文件路径AppDomain.CurrentDomain.BaseDirectory Config\\EapSectionState.json或固定路径便于备份。序列化使用System.Text.Json.NET 6内置高性能。扩展性未来可存储更多信息如StartedAt时间戳、启动者。3.2 优化后的EapSectionStateManager完整代码usingSystem.Text.Json;usingSystem.Collections.Generic;usingSystem.IO;usingSystem.Threading;publicstaticclassEapSectionStateManager{privatestaticreadonlyHashSetstring_startedSectionsnewHashSetstring(StringComparer.OrdinalIgnoreCase);privatestaticreadonlyobject_locknewobject();privatestaticreadonlystring_stateFilePathPath.Combine(AppDomain.CurrentDomain.BaseDirectory,Config,EapSectionState.json);// 静态构造函数程序启动时自动加载staticEapSectionStateManager(){LoadFromFile();}privatestaticvoidLoadFromFile(){try{if(!File.Exists(_stateFilePath))return;stringjsonFile.ReadAllText(_stateFilePath);varlistJsonSerializer.DeserializeListstring(json);if(list!null){lock(_lock){_startedSections.Clear();foreach(varsectioninlist)_startedSections.Add(section);}m_Log.Info($EAP状态已从文件恢复共{list.Count}个section);}}catch(Exceptionex){m_Log.Error($EAP状态文件加载失败使用空状态:{ex.Message},ex);// 安全回退不抛异常}}privatestaticvoidSaveToFile(){try{Directory.CreateDirectory(Path.GetDirectoryName(_stateFilePath)!);Liststringlist;lock(_lock){listnewListstring(_startedSections);}stringjsonJsonSerializer.Serialize(list,newJsonSerializerOptions{WriteIndentedtrue});// 原子写先写临时文件stringtempFile_stateFilePath.tmp;File.WriteAllText(tempFile,json);File.Move(tempFile,_stateFilePath,overwrite:true);m_Log.Debug($EAP状态已持久化到文件 ({list.Count}个section));}catch(Exceptionex){m_Log.Error($EAP状态保存失败:{ex.Message},ex);}}publicstaticvoidMarkAsStarted(stringsectionId){if(string.IsNullOrWhiteSpace(sectionId))return;lock(_lock){if(_startedSections.Add(sectionId)){m_Log.Info($EAP 启动标记成功 section:{sectionId});SaveToFile();// 立即持久化}else{m_Log.Warn($EAP 重复启动尝试 section:{sectionId});}}}publicstaticvoidMarkAsEnded(stringsectionId){if(string.IsNullOrWhiteSpace(sectionId))return;lock(_lock){if(_startedSections.Remove(sectionId)){m_Log.Info($EAP 结束标记成功 section:{sectionId});SaveToFile();// 立即持久化}}}publicstaticboolIsStarted(stringsectionId){if(string.IsNullOrWhiteSpace(sectionId))returnfalse;lock(_lock){return_startedSections.Contains(sectionId);}}/// summary/// 系统初始化/产线重启时强制清零可选调用/// /summarypublicstaticvoidClearAll(boolsaveImmediatelytrue){lock(_lock){_startedSections.Clear();if(saveImmediately)SaveToFile();}m_Log.Warn(EAP所有section状态已被清零);}}3.3 使用方式无需改动原有START/Ending逻辑启动时自动加载。每次MarkAsStarted/MarkAsEnded自动保存。程序退出时AppDomain.ProcessExit 或 手动调用可额外调用一次SaveToFile()。4. 进阶建议定时备份每天备份一次JSON文件到Backup\目录。版本控制JSON中增加Version: 1字段未来升级结构时自动迁移。SQLite替代方案如果section数量1000或需要查询历史使用Microsoft.Data.Sqlite单文件数据库建表EapStates (SectionId TEXT PRIMARY KEY, IsStarted INTEGER, UpdatedAt DATETIME)。优点事务保证一致性。监控与告警文件保存失败时触发SystemNotifEvent。安全考虑产线重启时是否调用ClearAll()建议增加配置开关RuntimeConfiguration.ResetEapStateOnStartup。5. 总结与实施路线立即实施采用JSON文件方案最优性价比。测试验证模拟程序崩溃、重启确认状态是否正确恢复。监控指标新增日志“EAP状态恢复成功/失败”便于运维。未来扩展若系统演进到分布式可无缝切换到Redis 事件溯源。这种持久化策略既符合SECS/GEM非易失性要求又保持了代码简洁性和工业级可靠性。如果您需要SQLite完整实现、配置化路径、或结合现有CIM/MES数据库的方案请提供更多系统架构细节我可以继续细化代码。
返回列表