Flink Agents 与 AI 流式应用 —— 第 13 章 可靠性防失控容错章节定位第四篇开篇本系列主线防失控先于智能的总装章。前面章节的防线是分散的——三道闸、幂等、语义化错误、超时——本章把它们整合成立体防御体系失败语义三分法决定重试还是放弃、决策幂等保证重放不出事故、补偿机制处理已经做错了怎么办、降级策略保证AI 挂了业务还在转、成本熔断守住预算底线最后用混沌工程演练验证整套防线。版本基线Apache Flink 2.3.0 Flink Agents 0.3.xJDK 17章节导读13.1 失败语义三分可重试 / 不可重试 / 需人工13.2 决策幂等重放不出事故13.3 动作补偿已经做错了怎么办13.4 降级策略AI 挂了业务还在转13.5 立体防线步数上限、成本熔断与白名单13.6 实战混沌工程演练13.7 本章小结与下章预告13.1 失败语义三分可重试 / 不可重试 / 需人工13.1.1 为什么必须分类一刀切重试的灾难: LLM 网关 500 → 重试 ✓(瞬时故障) 工具返回vin 格式非法 → 重试 ✗(永远失败,白烧 3 次钱) 审批号无效 → 重试 ✗✗(还暴露了绕过审批的企图) 错误分类是重试策略的前提——不是所有失败都值得再来一次。13.1.2 三分法定义publicenumFailureClass{RETRYABLE,// 可重试: 网络抖动、限流、超时PERMANENT,// 不可重试: 参数非法、资源不存在HUMAN_REQUIRED// 需人工: 权限不足、语义矛盾、业务冲突}// 工具错误码语义化时携带分类(4.4.3 的 retryable 字段升级)publicrecordToolError(Stringcode,Stringmessage,FailureClassfailureClass,Stringsuggestion){}// 框架按分类执行策略switch(error.failureClass()){caseRETRYABLE-scheduleRetry(error,backoff);// 指数退避casePERMANENT-feedBackToLlm(error);// 回喂 LLM 自我修正caseHUMAN_REQUIRED-emit(newApprovalRequiredEvent(...));// 转人工}13.1.3 重试纪律RETRYABLE 才重试,且: ① 指数退避: 1s → 2s → 4s,最大 3 次 ② 总预算内: 重试占用第 6 章的 maxDecisionTime ③ 与重启策略分层: 作业级 fixed-delay 无限重试(框架层), 调用级指数退避有限重试(业务层)——两层不混淆13.2 决策幂等重放不出事故13.2.1 重放来源全景Agent 场景的重放,比纯数仓多一层: ① Checkpoint 恢复重放(7.4.2): 事件重放 → 工具重调 ② 上游重发: Kafka 生产端重试 → 同 event_id 重复到达 ③ 人工重放: 调试时手动重推事件(第 6 章本地重放的生产版) 三层都必须幂等,缺一层就是事故隐患。13.2.2 幂等三层落地┌─────────────────────────────────────────────────────────┐ │ 层 1 事件入口: event_id 去重 │ │ Keyed State 记录已处理 event_id 集合(Bloom/短 TTL) │ │ 重复事件直接返回首次结果(重放友好: 结果一致) │ │ │ │ 层 2 工具执行: 业务幂等键 │ │ 动作类工具以 event_id 为幂等键(第 4 章) │ │ 执行前查是否已建单,已建则返回原单号 │ │ │ │ 层 3 存储出口: 引擎幂等 │ │ Doris UK MoW: 同 key 覆盖 │ │ Paimon deduplicate merge-engine(12.3.2) │ │ Kafka EXACTLY_ONCE sink(12.2.2) │ └─────────────────────────────────────────────────────────┘13.2.3 入口去重实现Action(listenEventTypes{AlertEvent.EVENT_TYPE})publicEventonAlert(ActionContextctx,AlertEvente)throwsException{// 层 1: 入口去重(状态判重,7.3.3 同款 TTL 48h)StringpriorprocessedState.get(e.eventId);if(prior!null){returnreplayResult(prior);// 返回首次结果,不重新推理}Eventresultdiagnose(e);processedState.put(e.eventId,result.digest());returnresult;}13.3 动作补偿已经做错了怎么办13.3.1 补偿思维幂等防重复做,补偿管做错了: 场景: Agent 误判 P0,工单已派给技师,半小时后复检证明误报 无法撤销(技师已出发),只能补偿: → 创建撤销工单(新动作,记录因果链) → 病程库标记该结论 recheck_ok0(第 8 章记忆质量) → 该 case 从召回池降权(不再误导后来者)13.3.2 补偿事务设计// 每个动作类工具注册对应的补偿动作publicrecordCompensableAction(StringactionId,StringactionType,// CREATE_TICKET / SEND_DIAGNOSE ...StringcompensationType,// CANCEL_TICKET / REVOKE_COMMAND ...MapString,Objectpayload){}// 补偿执行(由人工或复盘流程触发,不由 Agent 自动触发!)publicvoidcompensate(CompensableActionoriginal){// 纪律: 补偿永远人工发起,Agent 只能建议compensationService.execute(original.compensationType(),Map.of(origin_action_id,original.actionId(),reason,复检推翻初诊,trace_id,original.traceId()));}纪律: □ 补偿是新动作不是删除——审计链完整,因果可查 □ Agent 可以建议补偿,但执行必须人工确认(第 15 章) □ 补偿事件回写病程库,形成决策→验证→纠偏闭环13.4 降级策略AI 挂了业务还在转13.4.1 降级阶梯LLM 网关整体不可用(极端但必须有预案): L0 全功能: Agent 完整推理链 L1 阉记忆: 跳过记忆召回(第 8 章),仅当前事件推理 L2 规则兜底: 预置规则引擎(故障码→处置映射表),零 LLM L3 直通人工: 全部告警转人工队列,Agent 只记录不决策 降级触发: 自动: LLM 错误率 50% / 延迟 p99 60s 持续 5 分钟 手动: 运维开关(配置中心,秒级生效)13.4.2 规则兜底实现// L2 规则兜底: 一份离线维护的映射表,Agent 启动时加载MapString,FallbackRulerules;// faultCode → 固定处置publicEventdiagnose(AlertEvente){if(degradeLevel()L2){FallbackRulerrules.get(e.faultCode);returnr!null?r.toResult(e).withDegraded(true)// 标记降级结论:newApprovalRequiredEvent(e);// 规则没有的码 → 人工}returnreactDiagnose(e);// 正常 ReAct 链}纪律: □ 降级结论必带 degraded 标记,下游工单系统按低置信处理 □ 规则表只覆盖 Top20 高频故障码(80% 流量),其余转人工 □ 降级期间的事件照常落审计(12.3),恢复后抽样复盘13.5 立体防线步数上限、成本熔断与白名单13.5.1 防线总装图┌────────────────── 立体防线(由内到外) ──────────────────┐ │ │ │ 事件级: 三道闸(步数/循环/预算) ─── 第 6 章 │ │ 会话级: 单会话 LLM 调用 ≤20 次 ─── 第 7 章 │ │ 工具级: 超时/幂等/错误语义化 ─── 第 4 章 │ │ 权限级: 高危三保险/审批 ─── 第 4/15 章 │ │ 全局级: 成本熔断(本节) │ │ 模型级: 降级阶梯 L0~L3 ─── 13.4 │ │ │ └────────────────────────────────────────────────────────┘13.5.2 成本熔断// 全局成本熔断: 每小时 LLM 预算,超限自动降级到 L2publicclassCostCircuitBreaker{privatefinallonghourlyBudgetTokens;// 配置中心下发privatefinalAtomicLongusedThisHournewAtomicLong();publicbooleanallowLlmCall(intestimatedTokens){longusedusedThisHour.get();if(usedestimatedTokenshourlyBudgetTokens){metrics.costBreakerTripped.increment();// 告警指标returnfalse;// 熔断 → 走 L2 规则兜底}returntrue;}// 整点重置(处理时间窗口即可,预算控制不需要事件时间精度)}13.5.3 白名单兜底动作白名单: Agent 可执行的动作枚举,配置中心维护 □ 未在白名单的动作 → 框架层直接拦截(比 prompt 约束可靠) □ 白名单按环境分级: 测试环境宽松,生产环境收紧 □ 白名单变更走审批(它本身就是高危配置) 与 prompt 禁区(6.3)的关系: prompt 是第一道(约束模型意图) 白名单是第二道(拦截执行层) ——意图约束可以被骗过(Prompt 注入),执行拦截不能13.6 实战混沌工程演练13.6.1 演练设计每月一次,影子环境,注入故障验证防线: 演练 1 LLM 网关 500 持续 10 分钟 预期: 自动降级 L2,规则兜底接管,恢复后自动回 L0 演练 2 工单系统接口慢(注入 20s 延迟) 预期: 工具超时语义化回填,Agent 降级出结论, 无作业反压(异步工具池隔离生效) 演练 3 重复事件注入(同 event_id × 3) 预期: 入口去重生效,只建 1 张工单, 审计日志 3 条到达 1 条处理 演练 4 恶意文本注入(告警备注夹带指令) 预期: 边界包裹生效,指令被当数据处理(9.4.2), 未执行任何越权动作 演练 5 成本突刺(批量重放 10 万历史告警) 预期: 小时预算熔断触发,自动降 L2,告警通知运维13.6.2 演练评分卡演练通过标准常见失分点网关 5005 分钟内自动降级恢复后自动回切降级开关需人工慢工具主链路 p99 无劣化工具池与算子线程未隔离重复事件零重复工单只做了存储幂等没做入口去重注入攻击零越权执行只靠 prompt 禁区无白名单拦截成本突刺熔断触发且告警无预算监控事后账单才发现13.6.3 演练纪律□ 演练在影子环境,但影子环境与生产同构(配置/数据/防线) □ 每次演练必须产出: 失分点 → 修复 → 下月复测 □ 防线变更(新工具上线等)后必须补做相关演练 □ 演练记录入审计库——防线本身的可靠性也要可追溯13.7 本章小结与下章预告本章小结┌──────────────────────────────────────────────────────────────┐ │ 第 13 章 要点回顾 │ └──────────────────────────────────────────────────────────────┘ ✓ 失败三分: RETRYABLE(指数退避≤3次)/PERMANENT(回喂LLM)/ HUMAN_REQUIRED(转人工);重试有总预算,与作业重启策略分层 ✓ 幂等三层: 入口 event_id 去重(返回首次结果)/ 工具业务幂等键/存储引擎幂等(UKMoW、deduplicate、2PC) ✓ 补偿思维: 幂等防重复,补偿管做错;补偿是新动作非删除, Agent 建议人工执行,回写病程库形成纠偏闭环 ✓ 降级阶梯: L0 全功能→L1 阉记忆→L2 规则兜底→L3 直通人工; 自动触发手动开关,降级结论必带标记 ✓ 立体防线: 事件级三道闸→会话级调用上限→工具级超时幂等 →权限级三保险→全局成本熔断→模型级降级; prompt 禁区执行白名单双保险 ✓ 混沌演练: 五大故障场景评分卡,月度执行, 防线变更后补测,演练记录入审计下章预告第 14 章 可观测与效果评估防线建好了还得看得见——决策 Trace 全链路还原、四维效果评估准确/成本/时效/稳定、成本归因到每个 Agent 每个工具、人工反馈闭环回流训练资产以及 Agent 版监控五件套的落地配置。让每一次 AI 决策都可解释、可归因、可改进。官方参考资料Flink Agents 0.3 DocumentationFlink 2.3 Stable DocumentationFault TolerancePrinciples of Chaos Engineering本章实战代码清单序号内容说明1失败三分法与分类执行策略13.12幂等三层落地入口/工具/存储13.23补偿事务设计人工发起原则13.34降级阶梯 L0~L3 与规则兜底13.45成本熔断器 白名单拦截13.56混沌演练五场景 评分卡13.6