--- tags: [] date created: 星期五, 十一月 21日 2025, 3:14:02 下午 date modified: 星期一, 十一月 24日 2025, 4:31:32 下午 --- # 2.3.4 故障传播与恢复信令 (Fault Propagation & Recovery Signaling) 这是系统的“求救与自愈”机制。在 2.3.3 中,我们定义了正常的生老病死;而 2.3.4 则要定义当模块“意外暴毙”时,系统如何避免全面崩溃,并有序地重新站起来。 特别需要注意的是,根据您的 **附件:生产环境架构加固指南**,我们引入了父进程 Watchdog。因此,本节的故障处理必须划清界限:**逻辑故障归调度器管,进程崩溃归 Watchdog 管**。 ## 一、 约束输入与对齐 (Constraints & Alignment) 基于设计文档,我们需对齐以下硬性约束: 1. **职责边界**: - **模块职责**:严禁在内部无限重试致命错误(如 GPU ECC 错误),必须立即停止并上报。 - **调度器职责**:作为唯一决策者,负责编排恢复流程。 - **Watchdog 职责**:仅在整个进程 Segfault 或调度器死锁时介入。 2. **依赖感知**:恢复不能只重启故障模块,必须先暂停其上游的数据流,防止积压导致 OOM(内存溢出)。 3. **防风暴**:必须集成熔断机制,防止一个持续故障的模块引发系统无限重启循环。 --- ## 二、 权衡分析与选项呈现 (Trade-off Matrix) ### 议题 1:故障上报内容的标准化 (Fault Reporting Standard) |**选项**|**A. 仅错误码 (Error Code Only)**|**B. 丰富上下文 (Rich Context) (推荐)**| |---|---|---| |**机制**|`ModuleFailedEvent { int code; }`|`ModuleFailedEvent { ErrorCode code; string reason; Snapshot state; TraceID trace; }`| |**诊断能力**|**低**。日志里只能看到 "Error 1001",无法知道当时 GPU 显存剩多少,或者正在处理哪一帧。|**高**。携带了案发现场的快照和 TraceID,能直接关联到导致崩溃的那条控制指令。| |**传输开销**|极低。|低(拷贝几个字符串和结构体)。| |**决策支持**|弱。调度器只能无脑重启。|**强**。调度器可根据 `reason` 决定是立即重启,还是降级运行。| ### 议题 2:恢复编排策略 (Recovery Orchestration) |**选项**|**A. 激进重启 (Aggressive Restart)**|**B. 依赖感知流水线 (Dependency-Aware Pipeline) (推荐)**| |---|---|---| |**机制**|收到故障立即调用 `module->stop(); module->start();`。|`Pause Upstream` -> `Stop Faulty` -> `Start Faulty` -> `Resume Upstream`。| |**数据安全性**|**低**。上游模块还在疯狂推数据,故障模块重启期间,中间队列瞬间爆满,导致丢包或内存溢出。|**高**。先截断水源,再修水管,修好再放水。| |**复杂度**|低。|中。需要 `DependencyGraph` 支持。| --- ## 三、 基线确立与实施规范 为了实现“不仅能活过来,而且不丢数据”的智能恢复,我们确立 **B. 丰富上下文** 和 **B. 依赖感知流水线** 为基线。 ### 1. 故障事件信封基线 (`ModuleFailedEvent`) 我们定义一个标准化的故障事件结构,作为所有模块的“遗言”。 ```cpp struct ModuleFailedEvent : public BaseEvent { std::string module_name; ErrorCode error_code; bool is_hardware_fault; // 提示调度器:硬件坏了重启也没用,不如报警 std::string debug_info; // 包含显存状态、队列深度等现场快照 // 构造时自动捕获 TraceID ModuleFailedEvent(string name, ErrorCode code, string info) : module_name(name), error_code(code), debug_info(info) { is_hardware_fault = IsHardwareError(code); } }; ``` ### 2. 恢复信令时序基线 (Recovery Signaling Sequence) 这是调度器收到 `ModuleFailedEvent` 后的标准**四步走**恢复协议。以 `SignalProcessor` (信号处理) 崩溃为例,其上游是 `DataReceiver` (数据接收)。 1. **止血 (Pause Upstream)**: - 调度器发布 `PauseDataFlowEvent(target="DataReceiver")`。 - `DataReceiver` 响应:停止向中间队列 `push` 数据,暂时丢弃新数据或存入 RingBuffer,并回复 `DataFlowPausedEvent`。 2. **清理 (Stop Faulty)**: - 调度器发布 `StopModuleEvent(target="SignalProcessor", force=true)`。 - `SignalProcessor` 响应:尝试释放 GPU 资源,清理线程。回复 `ModuleStoppedEvent`。 3. **重启 (Restart Faulty)**: - 调度器发布 `StartModuleEvent(target="SignalProcessor")`。 - `SignalProcessor` 响应:重新初始化 CUDA 上下文,申请内存。回复 `ModuleRunningEvent`。 4. **恢复 (Resume Upstream)**: - 调度器发布 `ResumeDataFlowEvent(target="DataReceiver")`。 - `DataReceiver` 响应:恢复向中间队列推送数据。系统恢复正常。 ### 3. 熔断器集成基线 (Circuit Breaker) 为了防止“垂死挣扎”引发日志爆炸和 CPU 满载,必须在调度器侧实施熔断。 - **策略**:针对每个模块维护一个滑动窗口(如 60 秒)。 - **阈值**:若窗口内收到 **3 次** `ModuleFailedEvent`。 - **动作**: - 标记该模块状态为 `BROKEN`。 - 不再执行上述恢复流程。 - 发布 `SystemDegradedEvent`(系统降级)或 `SystemFailedEvent`(全系统停机)。 - 记录一条 `FATAL` 日志,呼叫运维人员。 --- ## 总结与下一步行动 我们确立了 **2.3.4 故障传播与恢复信令** 的基线: 1. **协议**:**丰富上下文上报**(带 TraceID 和现场快照)。 2. **编排**:**依赖感知的四步恢复法**(Pause -> Stop -> Restart -> Resume)。 3. **防护**:**三振出局**的熔断机制。 下一步建议: 系统能跑能修了,但在资源紧张(比如 GPU 满载)的时候,如何让重要任务(如显控界面渲染)优先运行?这就涉及到 2.3.5 资源仲裁与抢占式优先级控制。这是一个涉及“权力分配”的关键接口。 **提问**:您是否确认 **“依赖感知四步恢复 + 熔断器”** 的故障处理基线?确认后我们将深入 2.3.5。