feat: 补齐上游细节、渠道观测与模型定价元数据
- 上游 429 的 Retry-After 转成渠道冷却时长(夹在 10 分钟内;比默认值短则不缩短, 否则 1s 就把坏渠道放回轮转)。失败计数改由 proxyOne 就地报——只有它读得到响应头。 - 故障转移时间预算 OT_PROXY_FAILOVER_BUDGET(默认 30s):只约束第二个及以后的渠道, 首个不受限(长回答本就要跑几分钟),但坏渠道不再把客户端拖到 N×timeout。 - 流式空闲心跳 OT_PROXY_STREAM_HEARTBEAT(默认 15s):补一行 SSE 注释 `: ping`, 防止 nginx/Cloudflare 的空闲超时掐掉长思考。心跳与正文共用一把写的锁, gin 的 ResponseWriter 不是并发安全的;注释行不进转换也不计费。 - 渠道观测:GET /api/v1/admin/channels/stats?window=5m|1h|6h|24h|7d 聚合请求量、 成功率、P50/P95/max 延迟、成本与 top_errors;分位只取成功样本,canceled(客户端 主动断开)不计入渠道错误率。渠道页桌面表格加「近N小时」列、移动端加同内容条, 顶部可切窗口。 - 修一个让统计瞎掉的归因问题:全部渠道失败时 recordError 传的是 nil, usage_logs 里 channel_id=0,这类失败在渠道维度完全看不见。改为归到最后一个 真正试过的渠道。 - 模型定价与元数据:Model 新增 cache_write_price(0 则回退输入价×1.25,可显式配 Anthropic 1h 的 ×2)、context_length 与 supports_tools/vision/reasoning; finishUsage 走 CacheWritePriceOr()。/v1/models 叠加用户与密钥白名单过滤 (原来会把限制外的模型名直接泄漏在列表里)并返回元数据,价格不外泄。 - /v1/models 的 Anthropic 分支原是死代码:协议只按路径判,而两种客户端共用这个路径。 改为按 x-api-key / anthropic-version 头判,OpenAI SDK 从不发这两个头,互不影响。 - NewGateway 的十个位置参数换成 Options 结构体(三个 Duration 两个 int,传错编译期发现不了)。 新增 6 个用例:Retry-After 两种写法与夹顶、重试预算截止、空闲心跳出帧、 /v1/models 过滤与双形状、缓存写价两条路径、失败归因。
This commit is contained in:
1 parent
ad10bdc400
commit
c39c3e7da4
16 files changed
+984
-125
No files matched your search
@@ -10,12 +10,15 @@
|
||||
- `POST /v1/chat/completions` — OpenAI Chat(非流式 + 流式 SSE)
|
||||
- `POST /v1/responses` — OpenAI Responses API(非流式 + 流式事件)
|
||||
- `POST /v1/messages` — Anthropic Messages API(非流式 + 流式事件)
|
||||
- `GET /v1/models` — 可用模型列表
|
||||
- `GET /v1/models` — 可用模型列表:只列调用方真能用的模型(叠加用户与密钥白名单),带上下文长度与能力位;Anthropic 客户端(带 `x-api-key`/`anthropic-version`)返回 Anthropic 形状
|
||||
- **三协议互转**:客户端协议 × 渠道协议不匹配时自动转换(如 Chat 调用 Claude、Messages 调用 OpenAI、Responses 调用 Claude),流式逐事件转换;协议匹配时直通
|
||||
- 错误按客户端协议返回(OpenAI 格式 / Anthropic 格式)
|
||||
- **渠道体系**:按模型绑定选渠道 + 加权负载均衡;模型已有绑定时只用绑定渠道(都不可用则 503,不会把请求发给不认识它的渠道);每渠道并发信号量(满载溢出);后台健康检查(探测 `/models`,连续失败进 cooldown、恢复放回)+ 运行期健康(连续 3 次网络错误/超时/429/5xx 进 30s 冷却,成功即清零);可安全重试的失败自动故障转移(网络错误/429/5xx/超时且未写出响应头)
|
||||
- **上游超时**:渠道 `timeout_ms` 生效——非流式为整段请求上限,流式仅约束首包(正文不限时长);上游请求绑定客户端 context,断连即取消
|
||||
- **故障转移与流式细节**:上游 429 的 `Retry-After` 会延长该渠道冷却(夹在 10 分钟内);重试受 `OT_PROXY_FAILOVER_BUDGET` 时间预算约束(首个渠道不受限,避免坏渠道把客户端拖到 N×timeout);流式空闲超过 `OT_PROXY_STREAM_HEARTBEAT` 补一行 SSE 注释心跳,防止 nginx/Cloudflare 的空闲超时掐掉长思考
|
||||
- **渠道观测**:`GET /api/v1/admin/channels/stats?window=5m|1h|6h|24h|7d` 按渠道聚合请求量、成功率、错误码分布与 P50/P95 延迟;渠道页直接展示近况与运行期冷却剩余时间,可一键恢复
|
||||
- **限流/配额**(内存计数):密钥级每日请求数 / Token 数配额、用户级每秒速率(`OT_RATELIMIT_USER_RPS`);超限返回 429
|
||||
- **用量计费**:请求级 `usage_logs` 异步批量落库,按模型价格扣减余额,日粒度预聚合(`usage_daily`);模型可单独配置缓存写价(留空按输入价 ×1.25)
|
||||
- **认证面防护**:登录按「单 IP」+「单 IP×账号」双桶滑动窗口限速、注册按 IP 限速(429 + `Retry-After`);`/v1` 请求体上限 `OT_PROXY_MAX_BODY_MB`(超限按客户端协议返回 413);CORS 改为显式 origin 白名单(默认不发跨域头);`env=production` 启动时断言 JWT secret / 主密钥 / 管理员密码不能是仓库默认值,否则拒绝启动
|
||||
- **前端**:Dashboard / 管理总览骨架屏加载态
|
||||
- **用户体系**:注册(开放/邀请码可切换,管理后台可改)、登录(JWT access + HttpOnly refresh cookie)、argon2id 密码
|
||||
|
||||
Reference in new issue
Block a user