4.3 KiB
4.3 KiB
Overview
本次只实现“图片独立并发开关”,不实现外部图片网关的运行时代码。目标是在最大程度不改变现有行为的前提下,为图片流式长连接提供服务级资源保护。
Current Constraints
- 当前 Redis 并发槽位只有用户和账号维度,键语义是
concurrency:user:*与concurrency:account:*。 - 图片接口和普通 Responses 在同一个 Go 服务内运行,共享进程、HTTP 上游连接池和账号调度。
- Codex OAuth 路径会自动注入
image_generationtool;这个注入表示“模型具备工具能力”,不等价于当前请求一定会生图。 /v1/responses在 handler 入口只能可靠识别显式图片意图:image 模型、请求体已有 image tool、或 tool_choice 明确选择 image_generation。- 图片实际产物计数与计费仍以 service 层的最终输出解析为准。
Decisions
1. 默认关闭,保持兼容
新增配置:
gateway.image_concurrency.enabled,默认false。gateway.image_concurrency.max_concurrent_requests,默认0,表示不限制。gateway.image_concurrency.overflow_mode,默认reject,可选reject/wait。gateway.image_concurrency.wait_timeout_seconds,默认30,仅overflow_mode=wait生效。gateway.image_concurrency.max_waiting_requests,默认100,仅overflow_mode=wait生效,限制当前进程内图片等待队列。
只有当 enabled=true 且 max_concurrent_requests>0 时才启用图片独立并发限制。默认配置不改变任何现有流量行为。
2. 进程级信号量作为第一阶段隔离
本次使用进程内有界信号量做服务级图片并发限制。原因:
- 不扩展现有 Redis
ConcurrencyCache接口,避免影响用户/账号并发的既有语义。 - 不新增迁移,不改变分组已有字段。
- 单实例部署可立即保护进程资源。
- 多实例部署时该限制按实例生效;文档必须明确总图片并发约等于
实例数 × max_concurrent_requests。
3. 限制对象只包含明确图片意图
纳入限制:
/v1/images/generations/v1/images/edits/v1/responses中入口请求已明确包含图片意图:image 模型、tools[].type=image_generation、tool_choice明确选择 image_generation。
暂不纳入限制:
- 普通 Codex 请求因为服务端自动注入 image tool 而具备生图能力,但入口请求本身未明确要求生图。
这样避免把普通编码请求错误算作图片并发。后续若要对“模型运行中动态调用 image tool”做更细粒度隔离,需要在工具调用实际发生时获得可阻塞的事件,目前当前代码没有这种入口级阻塞点。
4. 限流行为
overflow_mode=reject时,未开始流式响应直接返回 HTTP429,错误类型rate_limit_error。overflow_mode=wait时,请求在当前进程内等待图片并发槽位,超过wait_timeout_seconds或超过max_waiting_requests后返回 HTTP429。- 已开始流式响应时,使用现有
handleStreamingAwareError写 SSE 错误事件。 - 图片并发限制命中或等待超时不触发账号 failover,不记录为上游账号失败。
gateway.image_stream_data_interval_timeout是上游图片流数据空闲超时,不用于图片排队等待。
5. 与外部图片网关的关系
本次不实现外部图片网关代码。外部网关方案沉淀到 2ue 文档:
- 推荐由 Caddy/Nginx/API Gateway 按
/v1/images/*分流。 /v1/responses的图片 tool 请求不能仅靠 path 分流,必须在前置层读取 body 或保留主服务兜底。- 即使未来拆出图片网关,主网关仍保留图片 intent 检测、开关和计费兜底,避免直连或漏判绕过。
Risks And Mitigations
- 风险:进程级限制在多实例部署下不是全局严格限制。缓解:文档明确容量计算,后续可基于 Redis 扩展为集群级图片并发。
- 风险:Codex 自动注入 image tool 后,普通编码请求未被图片限流。缓解:这是有意选择,避免误伤普通请求;实际输出图片仍按图片计费。
- 风险:图片请求在账号槽位前被拒绝可能改变排队体验。缓解:仅当独立开关启用时生效,默认关闭;429 明确提示图片并发达到上限。