126 lines
11 KiB
Markdown
126 lines
11 KiB
Markdown
# WCS 真实历史负载驱动全链路调度仿真设计
|
||
|
||
> **已取代:** 本设计允许从历史 `path_info` 推导测试拓扑,并允许报告
|
||
> `WAITING/FAILED`。经业务确认,这两个前提均不符合最终验收要求。后续实现以
|
||
> `2026-07-31-wcs-complete-center-dispatch-simulation-design.md` 为唯一依据。
|
||
|
||
## 1. 目标
|
||
|
||
把 `FT546-wcs.dbo.wcs_srgv_queue_finish` 固化的 240 条真实任务作为业务负载输入,验证调度中心从任务到达、重新选车、重新规划路径、交通裁决、模拟协议下发、逐段移动、资源释放到完成归档的完整功能。历史车辆号、历史路径和历史完成时间只作为对照,不控制仿真结果。
|
||
|
||
本测试是纯内存全链路仿真,不连接数据库、PLC 或 WMS,不修改 `ruoyi-*` 生产模块,不宣称现场 SHADOW、HIL 或生产可用性。PLC、车辆控制器和 WMS 均由行为完整、可注入故障的内存适配器模拟。
|
||
|
||
## 2. 方案比较
|
||
|
||
### 方案 A:继续固定历史车辆和路径
|
||
|
||
实现简单,但只能检查历史记录之间的路径交集,不能验证重新选车、路径规划和队列执行,不满足目标。
|
||
|
||
### 方案 B:仅把历史任务送入 LEGACY Demo
|
||
|
||
可以覆盖选车、BFS路径、模拟发送和归档,但不会经过新增 SHADOW 资源账本和滚动交通裁决,不能完整验证中央交通控制。
|
||
|
||
### 方案 C:历史负载驱动组合仿真(采用)
|
||
|
||
复用 `VehicleAssignmentService`、`GridPathPlanner`、`ShadowTrafficCoordinator`、`RollingDispatchPolicy` 和 `ResourceLedger`,增加独立仿真编排层。它既覆盖业务调度链,又经过当前交通安全内核,且保持生产代码零修改。
|
||
|
||
## 3. 输入口径
|
||
|
||
- 使用已固化并经 SHA-256 校验的 240 条真实历史记录。
|
||
- 每条数据库行都是独立任务。快照中 `task_no@guid` 只有 98 个唯一组合,因此唯一仿真 ID 为 `task_no@guid#stableSequence`;相同业务标识的多阶段或重复记录不合并。
|
||
- `create_date` 决定任务到达顺序和到达间隔。离散事件时钟支持 `10x`、`100x`,默认 `100x`;相同时间同时到达,超过 30 分钟的历史空闲间隔封顶为 18 仿真秒,避免测试等待数月。
|
||
- `task_type`:`1→INBOUND`、`2→OUTBOUND`、`3→RELOCATION`。
|
||
- `priority` 作为业务优先级;缺失时使用最低优先级。
|
||
- 历史 `agv_id` 只用于报告对照,调度中心必须重新选车。
|
||
- `start_site/end_site` 是业务输入。可直接映射到物理地图时直接使用;业务端点 `tsj` 等非物理节点通过显式端点映射转到该记录历史路径的首末有效节点,映射前后都写入报告。
|
||
- 历史 `path_info` 仅作为参考路径和离线测试拓扑的数据来源;规划器必须在拓扑上重新计算路线,不得把历史节点序列直接当作算法结果。
|
||
- 未知地图节点或无法形成物理端点的记录按 `INPUT_REJECTED` 失效关闭,不制造路径。
|
||
|
||
## 4. 仿真地图与车辆
|
||
|
||
从 240 条路径的全部有效相邻节点构造无向拓扑,并使用 `map-sites.json` 的 `x/y/z` 作为选车距离和楼层。所有节点及无向边容量均为 1;未签字的冲突区、提升机容量和安全 YIELD 点不自动推断。
|
||
|
||
车辆集合固定为真实样本中的 `1/2/3`。每辆车初始位置取该车最早有效记录的物理起点,状态为在线、自动、空闲、允许下发、电量 100。每辆车始终占用当前节点;移动时只申请“当前节点+下一条无向边+下一节点”的滚动资源包。
|
||
|
||
## 5. 队列、优先级与饥饿保护
|
||
|
||
到达任务进入统一等待队列。排序键依次为:`effectivePriority`、`create_date`、`task_no`、`guid`。数值越小优先级越高;空优先级使用最低业务优先级。每等待 30 仿真秒提升一级有效优先级,最多提升到最高级,使低优先级任务最终获得调度机会。任务发生资源 HOLD、车辆失效或协议发送失败后回到可调度状态;已占用但尚未移动的滚动资源立即释放,下一次调度允许重新选车和重新规划路径。
|
||
|
||
## 6. 每个仿真事件周期
|
||
|
||
1. 注入当前仿真时间已到达的真实任务,并按有效优先级重排等待队列。
|
||
2. 对空闲健康车辆和待调度任务调用现有选车规则;历史车辆号不参与约束。
|
||
3. 使用拓扑 BFS 规划“车辆当前位置→物理起点→物理终点”。无可达路线记录 `NO_ROUTE` 并失效关闭;新路线与活动剩余路线存在反向共享边时,在通道入口记录 `OPPOSITE_ROUTE_CONFLICT` 并 HOLD。
|
||
4. 为每个活动车辆构造不可变 `TrafficVehicleSnapshot` 和 `TrafficSnapshot`。
|
||
5. 为下一段移动构造 `ShadowCandidate`,调用 `ShadowTrafficCoordinator.run`。
|
||
6. `GRANT` 时把段资源写入内存权威账本;`HOLD/YIELD` 时保留任务等待并记录原因。
|
||
7. 模拟协议下发和 ACK。固定、可重复的故障计划使部分首次发送失败,按有界退避重试;每次失败、重试和最终结果记录原因。
|
||
8. ACK 成功后车辆前进一个节点,释放旧节点和已通过边,保留新节点。
|
||
9. 到达终点后完成并从活动队列原子迁移到归档队列;模拟 WMS 完成接收器使用任务 ID 作为幂等键,重复调用返回已处理结果且不产生第二次业务副作用。
|
||
10. 每 tick 检查资源容量、车辆唯一活动任务、完成幂等和确定性不变量。
|
||
|
||
## 7. 确定性故障矩阵
|
||
|
||
故障计划由固定种子和任务/车辆序号生成,不依赖墙钟随机数:
|
||
|
||
- PLC:部分任务首次发送失败、ACK 超时或 ACK 丢失;在最大 3 次内重试,成功后继续,耗尽后任务回队列并重新调度。
|
||
- 断线:车辆在指定事件序号断开,释放尚未执行的滚动资源,活动任务回队列;恢复连接后重新参与选车。
|
||
- 重启:PLC boot ID 改变,旧 ACK 被拒绝,车辆完成重新同步后继续。
|
||
- 低电量:车辆低于 30 时不再接新任务;正在移动的车辆到最近安全节点后 HOLD,电量恢复后重调度。
|
||
- 车辆故障:车辆变为不可用,活动任务回队列并由其他车辆重新选车;恢复后只接收新调度。
|
||
- 未知地图:输入端点或规划资源不在已校验地图时记录 `UNKNOWN_MAP` 并失效关闭。
|
||
- 无路可达:所有健康车辆均无法到达起点或起终点不连通时记录 `NO_ROUTE` 并失效关闭。
|
||
|
||
每种故障至少在受控单元场景中出现一次;240 条真实负载运行至少出现 PLC 失败/重试、HOLD 和车辆重新选择,其他故障通过同一仿真内核的确定性故障场景验证,避免为了覆盖而破坏真实负载结果。
|
||
|
||
## 8. 终止与失效关闭
|
||
|
||
- 全部任务完成或明确失败关闭后正常结束。最终状态统一归类为 `COMPLETED`、`WAITING`、`FAILED`,失败原因另列 `INPUT_REJECTED`、`UNKNOWN_MAP`、`NO_ROUTE`、`RETRY_EXHAUSTED` 等;`WAITING` 只允许出现在死锁或总时限触发后的最终快照,正常结束时必须为 0。
|
||
- 连续 500 个事件周期没有任何任务进入终态时标记 `DEADLOCK_TIMEOUT`;车辆往返移动、重复 HOLD 或重新分配不能重置该计数,以识别活锁。
|
||
- 总 tick 上限为 20,000;超过上限测试失败。
|
||
- 未知资源、地图版本错配、陈旧快照、资源超容量或重复完成通知立即使测试失败。
|
||
- 不使用历史 `finish_date` 强制完成;它只用于历史耗时对照。
|
||
|
||
## 9. 验收指标
|
||
|
||
必须满足:
|
||
|
||
- 输入记录数 240,且原始任务号、GUID、历史车辆和业务端点可回查。
|
||
- 每条输入恰有一个最终分类:`COMPLETED`、`WAITING` 或 `FAILED`;失败必须有唯一、可审计的具体原因。
|
||
- 资源超容量、同点双占、对向边同时占用、重复 WMS 业务副作用均为 0;测试会主动重复投递完成回调以证明幂等。
|
||
- 至少出现一次调度中心重新选车,证明没有固定使用历史 `agv_id`。
|
||
- 受控多路径场景必须证明规划器没有固定返回 `path_info`;真实负载中的路径差异数按实际结果报告,允许唯一最短路与历史参考路径相同。
|
||
- 固定故障计划至少触发一次协议失败并成功重试。
|
||
- 低优先级任务等待超过老化阈值后有效优先级提升,且在资源可达时最终获得调度机会。
|
||
- HOLD 原因必须区分资源占用、对向边、车辆不可用、低电量、PLC 失败、ACK 超时、快照/地图问题;每次 HOLD 后均能重新进入调度。
|
||
- 断线、PLC 重启、低电量和车辆故障场景均完成资源回收、旧反馈拒绝和恢复后重调度验证。
|
||
- 完成任务全部存在且只存在一条归档记录;WMS 业务回调次数等于完成任务数,重复投递被幂等接收但不重复计数。
|
||
- 相同输入运行两次,逐任务终态、分配车辆、规划路径、HOLD次数和完成顺序完全一致。
|
||
- 现有 60 条人工安全场景和全部 Maven 测试继续通过。
|
||
|
||
完成率、等待数和路径差异数作为功能测试结果报告,不预设下限;如果出现 `WAITING`、`INPUT_REJECTED` 或 `NO_ROUTE`,报告必须列出原始任务和具体原因。安全指标任一非零则整体失败。
|
||
|
||
## 10. 指标口径与输出
|
||
|
||
等待时间为 `首次成功分配时间 - create_date到达时间`;完成时间为 `仿真完成时间 - create_date到达时间`。报告同时保存仿真时钟值、按倍率折算值和历史 `finish_date-create_date`。平均值、P95、P99 使用最近秩法:对升序样本取 `ceil(p*n)-1`;无样本时为 `null`,不得写 0 伪装结果。
|
||
|
||
汇总必须回答:240 条任务的完成/等待/失败数量;每车完成数;历史与模拟车辆、路径差异;资源双占、对向换边和死锁次数;等待/完成时间平均、P95、P99;HOLD 和重试原因分布;历史耗时与仿真耗时差值;归档完整性和 WMS 幂等结果。
|
||
|
||
生成新的独立目录:
|
||
|
||
```text
|
||
outputs/wcs-history-driven-dispatch-simulation-<runId>/
|
||
├── summary.json
|
||
├── task-results.csv
|
||
├── tick-events.csv
|
||
├── invariant-results.json
|
||
├── readable-report.xlsx
|
||
└── manifest.sha256
|
||
```
|
||
|
||
Excel包含“测试总览、任务结果、车辆统计、重新选车与路径、等待与重试、安全与归档、数据问题、来源与边界”八张表。首页必须标注“真实历史负载驱动纯内存仿真,不是现场 SHADOW/HIL/ACTIVE 验收”。
|
||
|
||
## 11. 明确不能证明的内容
|
||
|
||
该仿真可以验证纯内存调度功能、确定性和安全不变量,但不能证明真实 SQL 事务、真实 PLC 协议、WMS 回调、网络故障恢复、HIL 或生产可用性。这些仍需按 `docs/WCS算法优化/06-测试灰度与验收.md` 的 L2~L9 分层执行。
|