# FT546WMS 影子 v3 现场操作手册 ## 1. 这次部署做什么 目标分支:`test/ft546wms-shadow-v3-20260903`。 影子 v3 只观察算法建议,不改变 Legacy 分配结果。入库、自动出库、手动出库仍由原存储过程执行一次,原返回码、返回消息、库位和异常保持不变。正常业务请求只做固定大小的内存登记,不等待影子线程,也不在调用线程执行影子数据库、文件或同步日志操作。 影子后台会读取业务表,并且只写 `alg.*` 对象。它可能增加数据库 CPU 和 I/O,因此仍需低峰部署、监控和随时回滚。 ## 2. 固定安全边界 - 现场只允许一个 FT546WMS JVM,稳定版和影子版不能同时运行。 - 仓库固定为 `01`;原始数据中的 `1` 与 `01` 等价,`W02` 只用于诊断,不能覆盖配置。 - SQL Server 必须使用 Windows 集成认证;脚本不接收用户名和密码。 - 当前现场已有 v2 包,安装必须使用 `upgrade`,不能使用 `clean`。 - v2 到 v3 升级保留 `alg.decision_log`;发现未知 `alg` 对象、清单不完整或 manifest 不匹配时脚本会停止。 - 影子失败、过期、并发、超时、配置错误或输入缺失均 fail-open:Legacy 继续,影子样本作废。 - 不执行正式 ACTIVE 切换,不增加 WCS/PDA/理库/预留/回放功能。 ## 3. 部署前准备 现场负责人先记录: - SQL Server 名称和数据库名; - 当前 v2 测试开始时间和时区; - IDEA 当前 Run Configuration; - 当前稳定实例 PID 和端口; - 本次交付给出的精确 v3 提交号 ``; - 应用日志目录。 部署前先导出现有 v2 证据。不要卸载 v2: ```cmd cd /d C:\project\FT546WMS-SHANDOW call scripts\shadow-v3-export.cmd C:\project\FT546WMS-SHANDOW "" "" "" "C:\project\FT546WMS-v2-before-v3" "" ``` 如果当前代码还没有 v3 导出脚本,先用既有导出方式保存 `alg.decision_log`、诊断结果、日志、分支和提交号,再继续。 ## 4. 按顺序部署 v3 ### 第一步:停止 IDEA 中的 v2 稳定实例 记录停止时间,在 IDEA 点 Stop。用下面命令确认最多只有一个相关 JVM,最好为 0: ```cmd jps -lv | findstr /I "RuoYiApplication FT546WMS" ``` 停止和重新启动之间会有一次短暂停机,这是计划内中断。不要同时启动两个实例来消除停机,否则可能重复执行定时任务、消费或外部回调。 ### 第二步:同步精确分支和提交 ```cmd cd /d C:\project\FT546WMS-SHANDOW git fetch origin git switch test/ft546wms-shadow-v3-20260903 git pull --ff-only git rev-parse HEAD git status --porcelain ``` `git rev-parse HEAD` 必须等于交付的 ``,`git status --porcelain` 必须没有输出。若不一致,停止部署。 ### 第三步:执行只读预检 ```cmd call scripts\shadow-v3-preflight.cmd C:\project\FT546WMS-SHANDOW "" "" ``` 只有看到 `PREFLIGHT_OK` 才能继续。预检检查分支、精确提交、干净工作树、main 祖先、JVM 数量、SQL 连接、v2/v3 manifest 和当前快照;它不修改数据库。 ### 第四步:升级数据库包 当前现场是 v2,只执行: ```cmd call scripts\shadow-v3-install.cmd "" "" upgrade ``` 只有全新测试数据库、确认没有 `alg` schema 时才允许使用 `clean`。现场生产库不要使用 `clean`。 ### 第五步:设置 IDEA 环境变量 在影子 Run Configuration 中使用: ```text FORTUCKY_SHADOW_ENABLED=true FORTUCKY_ALGORITHM_MODE=SHADOW FORTUCKY_ALGORITHM_DATABASE_WRITES_ENABLED=true FORTUCKY_ALGORITHM_WAREHOUSE_ID=01 FORTUCKY_SHADOW_TIMEOUT_SECONDS=3 FORTUCKY_SHADOW_SNAPSHOT_MAX_AGE_SECONDS=60 FORTUCKY_SHADOW_QUIET_INTERVAL_MILLIS=1000 ``` 不要设置 `ACTIVE`,不要添加数据库密码,不要设置 replay、tidy、reservation 或 WCS callback 开关。 ### 第六步:只启动一次影子实例 在 IDEA 启动 v3。不要重复点击 Run。启动时后台会认领唯一实例并建立第一代快照;认领或刷新失败只会关闭影子可用性,不应阻止 Legacy 启动。 启动后检查: ```cmd jps -lv | findstr /I "RuoYiApplication FT546WMS" ``` 只能看到一个 FT546WMS JVM。 ### 第七步:做只读和受控业务检查 先完成登录、页面查询等只读检查,再由现场人员执行一笔受控入库、一笔自动出库和一笔手动出库。确认: - Legacy 返回码、消息、库位和设备动作与稳定流程一致; - 没有相同存储过程重复执行; - `alg.shadow_snapshot_state` 为仓库 `01` 的 `PUBLISHED`; - `alg.shadow_instance_heartbeat` 只有当前实例; - `alg.decision_log` 出现新的计划/比较记录; - 应用日志中的影子 warning 不包含业务载荷或异常消息。 ## 5. 立即停止条件 出现任一情况立即执行第 7 节回滚: - Legacy 结果、响应码、消息、库位或设备动作改变; - 同一个 Legacy 存储过程疑似执行两次; - 出现第二个 FT546WMS JVM; - `alg` 之外出现本次部署造成的数据写入或新对象; - WMS、WCS、PDA 或现场作业异常; - 正常接口延迟或数据库 CPU、I/O、锁等待超过现场阈值; - 快照长时间不是 `PUBLISHED`,或 `ERROR_*` 指标持续增长。 单条 `shadow_failure` 表示该影子样本失败开放,不等于 Legacy 失败;但必须记录时间并纳入分析。 ## 6. 连续观察和七天导出 至少连续观察 7 天,覆盖正常业务高峰、入库、自动出库和手动出库。期间不要重放业务来补影子样本。 观察结束后运行: ```cmd cd /d C:\project\FT546WMS-SHANDOW call scripts\shadow-v3-export.cmd C:\project\FT546WMS-SHANDOW "" "" "" "C:\project\FT546WMS-shadow-v3-export" "" ``` 成功时显示 `EXPORT_OK`。输出目录包含: - `deployment.txt`:分支、提交、工作树; - `runtime-processes.txt`:JVM 进程; - `environment-variable-names.txt`:仅环境变量名,不含值; - `sql-diagnostics.txt`:manifest、快照、心跳、输入覆盖、阻塞; - `comparison-detail.txt`:比较汇总和完整决策行; - `runtime-metrics.txt`:准入、跳过、错误和时延桶; - `inventory-parity.txt`:Legacy 与已发布快照库存差异计数; - `shadow-warnings.txt`:日志目录中的结构化影子 warning。 把整个输出目录压缩后交给分析,不要包含密码、令牌或与测试无关的个人信息。只有七天数据通过分析后,才讨论正式切换;本分支本身不执行 ACTIVE 切换。 ## 7. 回滚 首选回滚只关闭影子,不卸载数据库对象: 1. 在 IDEA 停止 v3,记录停止时间; 2. 设置 `FORTUCKY_SHADOW_ENABLED=false`; 3. 完整重启一次; 4. 检查只有一个 JVM; 5. 做登录、查询、受控入库和出库冒烟检查。 更彻底的应用回滚是停止 v3,切回现场原稳定源码/提交并用原 Run Configuration 启动。无论哪种方式,都先恢复业务服务,再处理数据库对象。 `alg.*` 可以保留供取证,稳定 Legacy 不依赖它。不要把卸载当作紧急回滚步骤。 ## 8. 可选卸载 只有满足全部条件才卸载:影子实例已停止、稳定服务已恢复、七天证据已导出并备份、DBA 已确认维护窗口。 ```cmd call scripts\shadow-v3-uninstall.cmd "" "" CONFIRM_UNINSTALL ``` 卸载器只接受精确口令 `CONFIRM_UNINSTALL`,并由 SQL 包再次校验 v3 manifest 和完整对象白名单。发现未知/缺失对象时会在删除前停止。不要修改 manifest 或脚本绕过保护。 ## 9. 自动化验证与残余风险 - 本地单元/静态测试不能替代 SQL Server 2016 备份副本演练。 - `READ UNCOMMITTED` 只用于观察,可能看到业务事务中间状态。 - 单线程容量一队列限制影子后台并发,但不能消除数据库资源竞争。 - 3 秒 worker 等待超时不等于 JDBC/SQL Server 一定在 3 秒内完成取消或回滚。 - 影子调用线程不等待后台,但主机和数据库资源竞争仍可能间接影响 Legacy,需要现场监控。