feat: 运行期渠道冷却可见并可手动恢复

运行期冷却只存在网关进程内存里,DB 的 health_status 看不见它:渠道被踢到
30s 冷却后,管理后台仍显示 healthy,模型也照常出现在 /v1/models,但请求
返回 503 no_channel,管理员只能去翻日志。

- channel.Service 增 RuntimeState(连续失败次数 + 冷却剩余)与 ClearRuntime;
  Gateway 包装出 ChannelRuntime / RecoverChannel 供管理端调用。
- GET /api/v1/admin/channels 每项返回 runtime_fails 与 cooldown_seconds。
- 新增 POST /api/v1/admin/channels/:id/recover:清运行期冷却与失败计数,并把
  探测写的 health_status 置回 healthy;不改 enabled,上游若真挂着,下一次探测
  或再连续 3 次请求失败会重新把它踢掉。
- 渠道页健康列下方显示「冷却中 Ns」/「连续失败 n/3」,仅在冷却或探测不健康时
  出现「立即恢复」按钮(卡片与桌面表格两套布局都覆盖)。

仍未处理:冷却到期是裸恢复、没有 half-open 试探;计数是进程内的,多实例各自
为战,要共享得等 Redis 那一步。
This commit is contained in:
Sakurasan committed 2026-10-17 01:19:03 +08:00
1 parent e865f69a41
commit d4c5263f1e
8 files changed
+166 -2

No files matched your search

+10
View File
@@ -64,6 +64,16 @@ func (g *Gateway) ResetModelPolicy() {
g.policyMu.Unlock()
}
// ChannelRuntime 渠道运行期健康快照:连续失败次数 + 冷却剩余时间(管理后台展示)。
func (g *Gateway) ChannelRuntime(id uint64) (fails int, remaining time.Duration) {
return g.ch.RuntimeState(id)
}
// RecoverChannel 立即清除渠道的运行期冷却与失败计数(管理后台手动恢复)。
func (g *Gateway) RecoverChannel(id uint64) {
g.ch.ClearRuntime(id)
}
// globalModelRestrictions 读取全局模型允许/禁止列表(缓存 modelPolicyTTL)。
func (g *Gateway) globalModelRestrictions() (allow, deny []string) {
g.policyMu.Lock()