3.5 KiB
3.5 KiB
Context
现有普通 Responses 流式已经具备较完整的断连续写能力:客户端写失败后可继续 drain 上游,并且具备数据间隔超时和 keepalive。图片流式路径目前仍然采用更直接的读写方式,客户端写失败会立即返回,上游读取也更容易跟随客户端取消而结束。
本次变更只针对图片流式路径,不改变普通文本流式路径的配置和行为。系统已经存在普通流式的后端超时配置,因此这里不引入页面级超时设置;图片流式只需要独立的后端默认值,让图片生成有更长的容忍窗口。
Goals / Non-Goals
Goals:
- 图片流式在客户端断开后继续读取上游,尽量保留最终图片结果与计费结果。
- 图片流式使用独立于普通流式的超时与 keepalive 默认值。
- 不修改现有普通流式配置项的含义,不要求管理员新增页面配置。
- 维持图片计费与图片结果计数的一致性。
Non-Goals:
- 不设计新的前端配置页面。
- 不修改普通文本流式的超时策略。
- 不改变图片计费公式或分组倍率语义。
Decisions
-
使用独立的图片流式配置键
- 选择:在后端配置中增加图片流式专用
image_stream_data_interval_timeout/image_stream_keepalive_interval。 - 原因:图片流式耗时显著更长,复用普通流式默认值会过早触发超时;独立键能避免影响现有文本流式。
- 备选方案:直接复用普通流式配置并在代码里按路径放大倍数。这个方案会让普通流式和图片流式共享语义,后续难以维护。
- 选择:在后端配置中增加图片流式专用
-
继续使用上下文 detach,而不是依赖客户端上下文
- 选择:图片流式请求向上游发起时使用
context.WithoutCancel派生的上下文。 - 原因:客户端断开时不应自动取消上游请求,否则无法收集最终图片结果,也无法完成图片计费。
- 备选方案:仍使用
c.Request.Context()并只在写失败后继续 drain。这个方案在客户端取消场景下无法保证上游读取继续进行。
- 选择:图片流式请求向上游发起时使用
-
只改图片流式路径,不改普通流式路径
- 选择:
/v1/images/*与Responses + image_generation两条图片流式链路单独处理。 - 原因:风险最小,避免回归普通文本流式和现有超时配置。
- 备选方案:统一重构所有流式处理。这个方案范围更大,验证成本更高,不符合本次“尽量少改现有行为”的目标。
- 选择:
-
不新增页面配置
- 选择:图片流式独立超时默认值写入后端配置,沿用当前配置加载方式。
- 原因:用户明确要求和当前设置行为统一,不需要额外页面输入项。
- 备选方案:前端增加图片超时配置项。这个方案会改变现有运维方式,也容易引入误配。
Risks / Trade-offs
- [Risk] 图片流式继续 drain 上游后,客户端已经断开但服务端仍占用连接与协程资源。→ [Mitigation] 只对图片流式启用更长但仍有限的专用超时,并保持与普通流式同样的 keepalive/超时退出机制。
- [Risk] 图片流式与普通流式的默认超时不同,运维如果只关注通用配置可能忽略图片专用值。→ [Mitigation] 在配置示例中明确标注图片流式专用默认值和用途。
- [Risk] 断连后继续读取可能导致日志中出现“客户端断开但最终成功”的状态。→ [Mitigation] 保留现有图片计费结果返回语义,同时让调用方在结果与错误并存时优先使用结果对象。