跳到主要内容
FluxMeter
English

写作

LLM 网关超时之后:未知用量不等于零用量

FluxMeter 本地故障实验:网关超时后缺失回执不等于零用量,Outbox 重试也补不回未知执行。解释 token 计量的证据边界与重试安全。

2026-10-24 · 架构 · 4 分钟阅读

实验结论与证据边界

2026-10-24,针对引擎提交 b4ede374ed9ecc863ec71095c37fd89633161309 的本地实验复现了:Mock Provider 记录 processed=true 与模拟 100/50 tokens,网关在收到回执前发生 ReadTimeout。没有真实模型推理、真实供应商调用或实际供应商费用证据。

8 项实验通过包含确认缺口的断言;64 项相关回归通过不代表端到端验收。Hybrid UNKNOWN 生命周期验收不通过,它仍是候选设计。Gateway、Custody 使用仓库源码,Redis 为真实隔离实例,Kafka ACK 为替身。实际 Java billing Lua 在 Redis 直接执行,但没有运行 Java/Flink/Kafka/ClickHouse 完整链路。

测试客户端工厂把 120 秒读超时缩为 0.15 秒,Mock 延迟 0.6 秒,生产源码未改。流式测试不证明浏览器或反向代理 SSE 行为。

Outbox 只能重放已经拥有的回执

非流式超时保留 Reservation,却没有 Usage Envelope,Outbox 为空,HTTP 500 没有返回预留身份。已有回执在模拟 Kafka 故障后可以原样重放;这不能证明系统能找回从未收到的回执。用量证据链的另一端,即客户级用量为何会与上游账单不一致,见客户级用量 vs 上游账单。

Mock 私有证据由测试操作员手工关联与提供。Custody 接收不等于验证供应商真实性;Trusted Envelope 的名称也不构成独立的供应商证明。HTTP 202 表示接收,不表示账单完成。

执行重试与用量投递重试必须分开

单次调用在该场景没有自动重试上游。但相同 Idempotency-Key、X-Request-ID 的客户端重发产生两次执行和两个 Reservation,关联头未传给 Mock。事件去重不能替代执行去重。

固定 payload 的 Custody 重复接收有效;相同预留与 tokens 再次调用 ingest_usage,会因重新生成 timestamp 改变 fingerprint 而冲突。应保存首次事件时间和规范化 payload,将投递尝试时间另存;真实 payload 变化仍应冲突。

UNKNOWN 不等于 ZERO

流式路径收到 SSE headers,却没有内容或回执,仍因存在正数预留写入 0/0 事件。随后同一 reservation-derived event ID 的 100/50 用量返回不可重试 conflict。冲突检查本身有效,错误在于先把缺失证据写成确定的零。

源码还把非流式成功响应中缺失 usage 的字段默认为零;这是额外静态发现,#001 没有覆盖。部分流式估计也应标注证据来源,不能默认为供应商可信用量。

释放预留不能消除未知责任

直接调用 expire_due 可幂等释放预留、写 alert 并删除记录,但这不能证明上游没有消费。Lua 在预留存在及先释放后结算两种条件下,首次扣除样例 $0.000045,重复窗口返回 SKIP。这是组件级证据,不是全链路 exactly-once billing。样例价格来自 Python 目录,未重新验证 Java 定价一致性。

默认预留期限为 15 分钟,记录 TTL 为 24 小时。持有资金期限、调查期限、证据保留必须分开;后台调度、并发释放结算、长期停机和迟到窗口仍待验证。

先做最小正确性修复,再决定完整 Hybrid

先阻止无回执变成零用量;调用前持久化租户范围内的执行身份、请求 fingerprint 和 Reservation 关联;超时返回可追踪 UNKNOWN;投递重试复用原始 payload。相同执行身份配不同请求必须冲突。

仅有本地执行登记也无法保证任意供应商 exactly once。派发前后崩溃仍可能不确定;没有经验证的供应商幂等或查询协议时,不应盲目重发。

候选路径为 RESERVED → DISPATCHED → UNKNOWN → EVIDENCE_RECEIVED → SETTLED,资金释放独立。迟到证据、更正、未解决终态需要明确规则。更正不能简单再发一条完整用量而导致重复扣费。完整自动对账、供应商适配器与审计界面可按需求延期,核心正确性不应延期。

复现与完整英文文章

下载 README、原始八项测试和隔离 runner。准备 Python 3.11 API 镜像与测试依赖后,从 bundle 目录执行下方命令。运行阶段禁止外网,仓库只读挂载,输出写入单独目录;脚本只清空它自己的临时 Redis。

原始证据含探索重跑,早期外部脚本计数索引错误修正并非产品修复。完整 make demo-proof 未执行;真实供应商、全链路租户隔离、回执验证、崩溃恢复、Flink 迟到事件与 ClickHouse 生命周期审计仍未验证。

sh reproduce.sh ../fluxmeter ./results