6.0 KiB
6.0 KiB
tags, date created, date modified
| tags | date created | date modified |
|---|---|---|
| 星期五, 十一月 21日 2025, 3:14:02 下午 | 星期一, 十一月 24日 2025, 4:31:32 下午 |
2.3.4 故障传播与恢复信令 (Fault Propagation & Recovery Signaling)
这是系统的“求救与自愈”机制。在 2.3.3 中,我们定义了正常的生老病死;而 2.3.4 则要定义当模块“意外暴毙”时,系统如何避免全面崩溃,并有序地重新站起来。
特别需要注意的是,根据您的 附件:生产环境架构加固指南,我们引入了父进程 Watchdog。因此,本节的故障处理必须划清界限:逻辑故障归调度器管,进程崩溃归 Watchdog 管。
一、 约束输入与对齐 (Constraints & Alignment)
基于设计文档,我们需对齐以下硬性约束:
-
职责边界:
- 模块职责:严禁在内部无限重试致命错误(如 GPU ECC 错误),必须立即停止并上报。
- 调度器职责:作为唯一决策者,负责编排恢复流程。
- Watchdog 职责:仅在整个进程 Segfault 或调度器死锁时介入。
-
依赖感知:恢复不能只重启故障模块,必须先暂停其上游的数据流,防止积压导致 OOM(内存溢出)。
-
防风暴:必须集成熔断机制,防止一个持续故障的模块引发系统无限重启循环。
二、 权衡分析与选项呈现 (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)
我们定义一个标准化的故障事件结构,作为所有模块的“遗言”。
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 (数据接收)。
-
止血 (Pause Upstream):
- 调度器发布
PauseDataFlowEvent(target="DataReceiver")。 DataReceiver响应:停止向中间队列push数据,暂时丢弃新数据或存入 RingBuffer,并回复DataFlowPausedEvent。
- 调度器发布
-
清理 (Stop Faulty):
- 调度器发布
StopModuleEvent(target="SignalProcessor", force=true)。 SignalProcessor响应:尝试释放 GPU 资源,清理线程。回复ModuleStoppedEvent。
- 调度器发布
-
重启 (Restart Faulty):
- 调度器发布
StartModuleEvent(target="SignalProcessor")。 SignalProcessor响应:重新初始化 CUDA 上下文,申请内存。回复ModuleRunningEvent。
- 调度器发布
-
恢复 (Resume Upstream):
- 调度器发布
ResumeDataFlowEvent(target="DataReceiver")。 DataReceiver响应:恢复向中间队列推送数据。系统恢复正常。
- 调度器发布
3. 熔断器集成基线 (Circuit Breaker)
为了防止“垂死挣扎”引发日志爆炸和 CPU 满载,必须在调度器侧实施熔断。
- 策略:针对每个模块维护一个滑动窗口(如 60 秒)。
- 阈值:若窗口内收到 3 次
ModuleFailedEvent。 - 动作:
- 标记该模块状态为
BROKEN。 - 不再执行上述恢复流程。
- 发布
SystemDegradedEvent(系统降级)或SystemFailedEvent(全系统停机)。 - 记录一条
FATAL日志,呼叫运维人员。
- 标记该模块状态为
总结与下一步行动
我们确立了 2.3.4 故障传播与恢复信令 的基线:
- 协议:丰富上下文上报(带 TraceID 和现场快照)。
- 编排:依赖感知的四步恢复法(Pause -> Stop -> Restart -> Resume)。
- 防护:三振出局的熔断机制。
下一步建议:
系统能跑能修了,但在资源紧张(比如 GPU 满载)的时候,如何让重要任务(如显控界面渲染)优先运行?这就涉及到 2.3.5 资源仲裁与抢占式优先级控制。这是一个涉及“权力分配”的关键接口。
提问:您是否确认 “依赖感知四步恢复 + 熔断器” 的故障处理基线?确认后我们将深入 2.3.5。