功能与行为
本章描述 ScootGate 当前提供的软件能力及其外部可观察行为。
客户端入口
ScootGate 提供三个需要 API key 的 HTTP 入口:
| 方法 | 路径 | 功能 |
|---|---|---|
POST | /v1/chat/completions | OpenAI-compatible 聊天与 SSE |
POST | /v1/messages | Anthropic Messages 与 SSE |
GET | /v1/models | 列出公共 OpenAI-compatible 模型 |
客户端使用公共模型名,ScootGate 在转发前把 model 改写为 target 的真实
Provider 模型名。未知模型、协议不匹配或能力不足都会在出网前拒绝。
精确请求、响应和错误格式见客户端 HTTP API。
授权
- 接受
Authorization: Bearer <key>或x-api-key: <key>; - 两者同时存在时 Bearer 优先;
- 控制面快照只包含原始 key 的 SHA-256 摘要;
- 未加载有效授权快照时所有客户端 key 都被拒绝;
- 新版本快照原子替换旧版本,吊销在下一份有效快照生效;
- 原始 key 不写入缓存、日志、MQTT 或用量 outbox。
ScootGate 不创建用户、租户、套餐或 API key;这些属于外部控制面。
强制出站代理
每个 Provider 连接只能经配置的 HTTP CONNECT 或 SOCKS5 代理建立。代理身份 是 ScootGate 专用服务身份,客户端 key 不会复制到代理或 Provider。
- 代理连接失败:返回网关错误;
egress.tls = true:验证代理证书;- HTTPS Provider:始终验证 Provider 证书;
- 不存在直连回落或跳过证书校验开关;
- 明文 Provider upstream 只允许 loopback 开发地址。
公共模型与 target
[models.<name>] 定义客户端可见模型;每个 target 绑定:
- backend ID;
- Provider 真实模型名;
- 相对权重;
- stream、tools、JSON schema 能力。
能力由请求体推导。需要某项能力的请求只在声明支持该能力的 target 中选择。 OpenAI-compatible 和 Anthropic Messages 使用独立协议池,不做隐式转换。
负载均衡
默认 weighted_p2c 从候选 target 中进行加权采样,再按以下信号选择:
- 相对权重;
- backend 本地在途数及容量;
- EWMA 首包延迟;
- 新 backend 慢启动。
weighted_random 是仅考虑权重的简化降级算法。权重表达相对选择意图,
不保证小样本严格百分比分配。
每个节点独立维护热状态,不依赖中心数据库、分布式锁或节点共识。
容量与故障隔离
每个 backend 具有节点本地 max_inflight_per_node 上限。达到上限后不再接受
新选择,其他健康 target 仍可接流。
传输故障按发送状态处理:
- DefinitelyNotSent:能证明请求字节未发出,可在总尝试上限内改选;
- PossiblySent:请求可能到达 Provider,绝不自动重试;
- ResponseReceived:已收到 Provider 响应。
连续传输失败触发熔断;冷却后只允许一个 half-open 探测。Provider 401/403 会停用整个 backend,429 原样返回并触发短暂冷却。
路由来源
Static
backends/models 随本地 TOML 加载,启动时完整校验。修改需要发布配置并重启进程。
Snapshot
backends/models 由控制面完整下发:
- schema 固定为 1;
- 版本必须严格递增;
- 未知 credential 引用、非法 URL、空模型池等会整体拒绝;
- 有效快照编译后原子替换;
- 请求在开始时固定一份路由表,热更新不影响在途请求;
- backend 身份未变时继承 EWMA、熔断、在途和停用状态;
- 控制面超期不可达时节点转 unready,但最后有效表继续服务。
用量事件与 outbox
每个完成的 Provider 路由生成 schema 2 非权威事件,包含租户/key 标识、 公共模型、真实模型、backend、发送状态、失败阶段、字节数、首包延迟和 Provider 原生 token usage。
事件先原子写入有界磁盘 outbox,再以 MQTT QoS 1 投递;收到 PUBACK 后删除。
断线或重启会使用稳定 event_id 重放,接收方必须去重。
outbox 满或不可写时按 drop_newest 丢弃新事件并计数,API 数据面继续服务。
该通道固定 authoritative = false,不能作为权威计费账本。
TLS、健康与停机
- API listener 可原生终止 TLS 1.2+;生产必须配置 TLS;
- health listener 独立于 API listener,不要求 API key;
/healthz表示进程存活;/readyz同时要求授权快照、路由就绪且节点未排空;- SIGINT/SIGTERM 后节点进入 draining,停止接收新连接并在 grace period 内 等待在途请求完成,超时后有界退出。
明确不提供的功能
- 用户、租户、套餐或 API key 管理控制面;
- Provider 直连回落;
- 可能已发送请求的自动重试、对冲或多 backend 竞速;
- 任意规则 DSL、脚本路由或跨协议转换;
- 权威计费账本;
- 公共 API 上的管理端点。