独家合作CubenceAI 中转平台立减 10%访问

供应商管理

供应商健康检查

供应商健康检查

供应商健康检查系统持续监控 AI 模型提供商,并自动管理其可用性。它能及早发现故障,防止连锁反应,并在供应商恢复在线时实现自动恢复。

概览

健康检查系统在多个层面运行:

  • 端点级探测 - 对供应商端点进行主动 HTTP 健康检查
  • 供应商级熔断器 - 基于请求的故障检测与隔离
  • Agent 级健康管理 - 针对 SSL 和协议错误的连接池监控

当供应商多次失败时,系统会开启其熔断器并停止发送请求。一旦供应商恢复,熔断器会逐渐关闭并恢复流量。

熔断器状态

熔断器使用三状态模式来管理供应商健康。

状态定义

状态描述行为
关闭 (Closed)正常运行请求正常流向供应商
开启 (Open)供应商异常请求被阻断,快速失败
半开 (Half-open)测试恢复允许少量请求以测试健康状况

状态转换

关闭 --[失败达到阈值]--> 开启 --[超时到期]--> 半开
   ^                                              |
   +-------------[成功达到阈值]-------+

开启熔断器: 当连续失败达到阈值(默认:5)时,熔断器开启并阻断所有请求。

进入半开状态: 在开启持续时间(默认:30 分钟)到期后,熔断器进入半开状态,允许少量请求通过。

关闭熔断器: 当半开状态下的成功次数达到阈值(默认:2)时,熔断器关闭,恢复正常运行。

配置

熔断器设置可以通过数据库或环境变量按供应商进行自定义。

默认配置

{
  failureThreshold: 5,           // 开启前的失败次数
  openDuration: 1800000,         // 30 分钟(毫秒)
  halfOpenSuccessThreshold: 2    // 关闭所需的成功次数
}

数据库结构

provider 表包含以下熔断器字段:

列名类型默认值描述
circuit_breaker_failure_thresholdinteger5开启熔断器前的失败次数
circuit_breaker_open_durationinteger1800000开启持续时间(毫秒)
circuit_breaker_half_open_success_thresholdinteger2关闭所需的成功次数

环境变量

通过环境变量配置智能探测系统:

变量默认值描述
ENABLE_SMART_PROBINGfalse启用主动恢复探测
PROBE_INTERVAL_MS10000智能探测间隔(10 秒)
PROBE_TIMEOUT_MS5000智能探测超时(5 秒)

端点探测

系统使用 HTTP 探测对供应商端点执行主动健康检查。

探测方法

探测采用高效的两步法:

  1. 首先尝试 HEAD 请求 - 更快,不需要响应体
  2. GET 备选 - 仅当 HEAD 返回空状态(网络/超时错误)时执行

健康判定

在以下情况下,端点被视为不健康:

  • HTTP 5xx 状态码(服务器错误)
  • 网络错误或超时
  • DNS 解析失败

HTTP 4xx 错误 被视为探测失败,因为它们通常表示客户端问题,而非供应商健康问题。

探测结果结构

{
  ok: boolean,              // 如果 statusCode < 500 则为 true
  method: "HEAD" | "GET",   // 哪个方法成功了
  statusCode: number | null, // HTTP 状态码或错误时的 null
  latencyMs: number | null, // 响应时间
  errorType: string | null, // "timeout", "network_error", "http_5xx"
  errorMessage: string | null
}

错误类型

错误类型描述
timeout请求超过超时限制
network_error连接失败,DNS 错误
invalid_urlURL 解析失败
http_5xx服务器返回 5xx 状态
unknown_error意外错误

探测调度器

探测调度器协调所有供应商端点的定期健康检查。

Leader 选举

在多实例部署中,只有一个实例运行探测:

  • 使用基于 Redis 的分布式锁
  • 锁键:locks:endpoint-probe-scheduler
  • 锁 TTL:30 秒(可配置)
  • 每 15 秒续期一次心跳

自适应间隔

探测频率根据端点特征进行调整:

场景间隔描述
基础60 秒默认探测间隔
单一供应商10 分钟仅有 1 个端点的供应商
最近超时10 秒出现过超时错误的端点

配置

变量默认值描述
ENDPOINT_PROBE_INTERVAL_MS60000基础探测间隔
ENDPOINT_PROBE_TIMEOUT_MS5000请求超时时间
ENDPOINT_PROBE_CONCURRENCY10并发探测工作线程数
ENDPOINT_PROBE_CYCLE_JITTER_MS1000每个周期的随机延迟
ENDPOINT_PROBE_LOCK_TTL_MS30000Leader 锁 TTL

智能恢复探测

当供应商熔断器开启时,智能探测系统通过定期使用实际 API 调用测试供应商,加速恢复检测。

工作原理

  1. 检测 - 识别处于开启 (OPEN) 状态的供应商
  2. 测试 - 发送实际的补全请求以验证 API 功能
  3. 转换 - 成功后,立即将熔断器移至半开 (HALF-OPEN) 状态
  4. 验证 - 真实流量逐渐确认恢复

这比 HTTP 探测更全面,因为它验证了供应商 API 是否真正能处理 AI 模型请求,而不只是端点响应 HTTP。

测试执行

测试服务使用以下参数执行补全测试:

{
  providerUrl: string,       // 供应商基础 URL
  apiKey: string,            // 认证密钥
  providerType: string,      // 决定请求格式
  model?: string,            // 要测试的模型
  latencyThresholdMs: 5000,  // 延迟阈值
  timeoutMs: 10000          // 请求超时时间
}

测试结果

字段描述
success整体测试是否通过
status"green", "yellow", 或 "red"
subStatus详细状态,如 "slow_latency", "auth_error"
latencyMs总请求延迟
firstByteMs首字节时间
content响应预览(已截断)

可用性监控

可用性服务根据实际请求历史计算供应商健康状况。

状态分类

请求根据结果进行分类:

状态条件含义
绿色 (Green)2xx/3xx 状态码成功
红色 (Red)4xx/5xx 状态码或 null错误
未知 (Unknown)无数据历史记录不足

当前状态计算

系统分析最后 3 个时间段(近期历史)以确定当前状态:

  • 如果无可用数据,则为 未知(不假设为健康)
  • 如果成功率 >= 50%,则为 绿色
  • 如果成功率 < 50%,则为 红色

可用性评分

score = greenCount / (greenCount + redCount)

1.0 的评分表示 100% 可用,0.0 表示完全故障。

供应商选择集成

健康检查系统与供应商选择集成,确保请求只发送到健康的供应商。

选择流水线

在路由请求时,供应商会经过多个过滤阶段:

  1. 分组预过滤 - 按用户/密钥供应商组过滤
  2. 基础过滤 - 检查启用状态、格式兼容性、模型支持
  3. 1M 上下文过滤 - 过滤掉禁用上下文偏好的供应商
  4. 健康检查 - 熔断器 + 消费限制
  5. 优先级分层 - 选择优先级最高的供应商
  6. 成本排序 + 加权选择 - 按成本排序,进行加权随机选择

健康过滤

filterByLimits 函数检查:

  1. 厂商类型熔断器 - 检查厂商和类型组合是否被阻断
  2. 供应商熔断器 - 检查单个供应商的熔断器状态
  3. 消费限制 - 验证 5 小时、每日、每周、每月的成本限制
  4. 总成本限制 - 检查累计消费限制

并发会话限制在原子操作中单独检查,以避免竞态条件。

决策上下文

系统跟踪每个阶段过滤掉了多少供应商:

context.beforeHealthCheck = candidateProviders.length;
const healthyProviders = await filterByLimits(candidateProviders);
context.afterHealthCheck = healthyProviders.length;

这使得日志中能够显示决策链可视化。

自动故障转移

当供应商在请求处理过程中发生故障时,系统会自动处理故障转移。

故障处理流程

  1. 记录故障 - 增加该供应商的失败计数
  2. 检查阈值 - 如果达到阈值,开启熔断器
  3. 触发告警 - 发送 Webhook 通知(如果已配置)
  4. 重试备选 - 请求可以使用链中的下一个供应商进行重试

恢复流程

当恢复中的供应商被成功探测时:

  1. 智能探测成功 - 转换到半开 (HALF-OPEN) 状态
  2. 限制流量 - 逐渐使用真实请求进行测试
  3. 成功跟踪 - 统计连续成功次数
  4. 完全恢复 - 在达到阈值成功次数后,关闭熔断器

告警通知

当熔断器开启时,系统可以发送 Webhook 通知以提醒管理员。

告警内容

通知包含:

  • 供应商名称和 ID
  • 触发开启的失败计数
  • 将尝试重试的时间戳
  • 最后一条错误信息

重复抑制

告警会在 Redis 中缓存 5 分钟,以防止针对同一供应商发送重复通知。

配置

支持两种通知模式:

  • 传统模式 - 单个 Webhook URL
  • 基于绑定的模式 - 带有供应商绑定的多个 Webhook 目标

settings.enabledsettings.circuitBreakerEnabled 中检查设置。

Agent 池健康

Agent 池独立于熔断器管理 HTTP 连接健康。

不健康 Agent 检测

在以下情况下,Agent 被标记为不健康:

  • 检测到 SSL 证书错误
  • 检测到 HTTP/2 协议错误

替换流程

  1. 在请求转发中检测到错误
  2. Agent 被标记为不健康并附带原因
  3. 在下一个请求时,不健康的 Agent 被剔除
  4. 为该请求创建新的 Agent

这可以处理连接层的问题,而不影响供应商的熔断器状态。

错误模式

SSL 错误: certificate, ssl, tls, cert_, self signed, hostname mismatch, unable_to_get_issuer_cert, cert_has_expired

HTTP/2 错误: GOAWAY, RST_STREAM, PROTOCOL_ERROR, ERR_HTTP2_, NGHTTP2_, HTTP_1_1_REQUIRED, REFUSED_STREAM

健康检查端点

基础健康端点

GET /api/actions/health

响应:

{
  "status": "ok",
  "timestamp": "2025-01-29T12:00:00.000Z",
  "version": "1.0.0"
}

由 Docker 健康检查和负载均衡器使用。

供应商健康状态 API

Action: getProvidersHealthStatus

仅限管理员的操作,返回所有供应商的熔断器状态:

Record<number, {
  circuitState: "closed" | "open" | "half-open";
  failureCount: number;
  lastFailureTime: number | null;
  circuitOpenUntil: number | null;
  recoveryMinutes: number | null;
}>

可用性查询 API

GET /api/availability

查询参数:

参数默认值描述
startTime24 小时前时间范围起点 (ISO 字符串)
endTime现在时间范围终点 (ISO 字符串)
providerIds全部以逗号分隔的供应商 ID
bucketSizeMinutes变化时间段大小(最小 0.25 分钟)
includeDisabledfalse包含已禁用的供应商
maxBuckets100最大时间段数量

当前状态 API

GET /api/availability/current

根据最后 15 分钟的数据,返回所有已启用供应商的轻量级当前状态。

仪表盘可视化

供应商设置页面

健康状态在供应商列表中以徽章形式显示:

  • 熔断器开启 - 带有恢复倒计时的红色徽章,手动重置按钮
  • 半开 - 表示恢复进行中的黄色徽章
  • 无徽章 - 关闭(健康)

管理员可以通过确认对话框手动重置熔断器。

可用性仪表盘

功能包括:

  • 摘要卡片 - 系统可用性,健康/不健康/未知计数
  • 时间范围选择 - 15 分钟, 1 小时, 6 小时, 24 小时, 7 天
  • 热力图可视化 - 随时间变化的可用性

颜色编码:

颜色可用性含义
绿色>= 95%极好
酸橙色80-95%良好
橙色50-80%降级
红色< 50%
灰色无数据未知

提示框信息:

  • 时间段
  • 总请求数
  • 可用性百分比
  • 平均延迟
  • 绿色/红色请求计数

状态持久化

熔断器使用双层持久化策略。

内存层(主要)

  • 请求处理期间快速访问
  • 无网络延迟
  • 进程重启时丢失

Redis 层(备份)

  • 跨实例共享
  • 进程重启后依然存在
  • 状态键具有 24 小时 TTL
  • 配置键无 TTL(永久)

同步策略

  • 直写 (Write-through) - 每次状态更改立即写入 Redis
  • 延迟读取 (Lazy read) - 仅当需要状态且内存中不存在时检查 Redis
  • 批量加载 - 为管理员查询并行加载所有状态

Redis 键结构

熔断器状态:

键名: circuit_breaker:state:{providerId}
类型: Hash
TTL: 86400 秒 (24 小时)

熔断器配置:

键名: circuit_breaker:config:{providerId}
类型: Hash
TTL: 无 (永久)

边缘情况与韧性

Redis 不可用

当 Redis 不可用时:

  • 熔断器以仅内存模式运行
  • 状态不跨实例共享
  • 重启后状态丢失
  • 缓存未命中时配置回退到数据库

Redis 客户端使用 enableOfflineQueue: false 以实现快速失败和指数退避重试策略。

多实例协调

  • Leader 选举确保只有一个实例运行探测
  • 熔断器状态在更改时立即持久化到 Redis
  • 启动时批量加载以提高效率

无数据场景

  • 当不存在请求数据时,可用性状态为 "未知" (而非 "绿色")
  • 新供应商从关闭 (CLOSED) 状态开始,失败次数为零
  • 这避免了错误地报告健康状态

超时处理

  • 探测超时默认为 5 秒
  • 出现超时错误的端点探测频率更高(10 秒间隔)
  • 请求超时不触发熔断器(仅失败触发)

供应商删除清理

当供应商被删除时:

  1. healthMap 中清除内存状态
  2. 删除 Redis 键
  3. 不留任何过期状态

最佳实践

调整熔断器阈值

场景建议
不稳定的供应商failureThreshold 降至 3,增加 openDuration
可靠的供应商保持默认值或将 failureThreshold 增加到 10
关键供应商halfOpenSuccessThreshold 降至 1 以实现更快恢复
测试环境减少所有超时时间以获得更快反馈

监控健康检查指标

要跟踪的关键指标:

  • 熔断器状态分布(关闭/开启/半开计数)
  • 各端点的探测成功/失败率
  • 平均探测延迟
  • 熔断器开启后的恢复时间

处理供应商维护

对供应商进行维护时:

  1. 在设置中禁用该供应商(防止新请求)
  2. 等待活动会话完成
  3. 执行维护
  4. 重新启用供应商
  5. 监控健康状态以确认恢复

或者,如果在维护期间触发了熔断器,维护完成后手动重置熔断器。

故障排除

熔断器意外开启

检查:

  • 日志中近期的供应商错误
  • 网络连通性问题
  • 认证失败(API 密钥过期)
  • 供应商的频率限制

供应商卡在开启状态

可能的原因:

  • 供应商确实宕机(通过直接 API 测试验证)
  • 智能探测已禁用 (ENABLE_SMART_PROBING=false)
  • 探测超时时间对于慢速供应商来说太短
  • Redis 连接问题阻止了状态同步

健康检查误报

如果探测通过但请求失败:

  • 探测使用 HEAD 请求,实际请求可能命中不同的端点
  • 检查供应商是否具有不同健康状况的多个端点
  • 如果某些模型失败,请查看特定模型的可用性

探测延迟高

如果探测缓慢:

  • 增加 ENDPOINT_PROBE_INTERVAL_MS
  • 检查到供应商的网络路径
  • 考虑与供应商端点的地理距离
  • 检查单一供应商间隔(10 分钟)是否合适
Previous
模型重定向