凌晨两点,我的生产环境监控系统突然告警。客服反馈大量用户反映 AI 对话功能超时无响应。我立刻打开日志面板,映入眼帘的是一连串触目惊心的错误:ConnectionError: timeout after 30 seconds。更糟糕的是,由于我们没有实现故障切换机制,整个服务在供应商 API 完全不可用时陷入了瘫痪状态。
这一次故障持续了整整47分钟,直接影响了约3000名用户的体验。作为一个日均调用量超过50万次的 AI 应用,这个代价太过沉重。正是这次经历让我下定决心,为我们的 HolySheep AI 接入层构建一套真正的高可用架构。
为什么你的 AI 中转站需要高可用架构
在深入技术细节之前,让我们先理解一个核心问题:为什么 AI 中转站的高可用性如此关键?
根据我对多个生产环境的观察,AI API 的稳定性远不如传统 REST API。OpenAI、Anthropic、Google 等主流供应商的 SLA 通常只承诺99.9%,这意味着每月仍有约43分钟的不可用时间窗口。更糟糕的是,这些宕机往往来得毫无预兆,可能是一次突发的流量洪峰,可能是区域性的网络抖动,也可能是一次未提前通知的维护窗口。
对于企业级应用而言,用户对 AI 服务的可用性期望是永不停机。当你向用户承诺"7×24小时智能客服"时,你的技术架构必须支撑这个承诺。HolySheep AI 作为国内领先的 AI 中转平台,不仅提供稳定的 API 接入服务,其基础设施本身也采用了多区域容灾设计,配合我们的架构方案可实现99.99%以上的有效可用性。
核心架构设计:三层防护体系
经过反复踩坑和优化,我总结出一套经过生产验证的三层防护架构。这套架构的核心思想是:本地缓存是第一道防线,智能路由是第二道防线,实时监控是第三道防线。
第一层:本地响应缓存与降级策略
当 AI 供应商完全不可用时,最理想的情况是系统能够自动切换到缓存的、历史正确的响应。这不能覆盖所有场景,但对于 FAQ 类问答、规则明确的对话等场景,这一层防护能救命。
"""
AI 高可用架构 - 本地缓存层实现
适配 HolySheep AI API v1
"""
import hashlib
import json
import time
import asyncio
from typing import Optional, Dict, Any
from dataclasses import dataclass, asdict
from collections import OrderedDict
@dataclass
class CacheEntry:
"""缓存条目结构"""
response: str
timestamp: float
ttl: int
model: str
provider: str
token_count: int
class LRU回应缓存:
"""基于 LRU 的本地响应缓存,最多存储 10000 条,内存占用约 500MB"""
def __init__(self, max_size: int = 10000, default_ttl: int = 3600):
self.cache: OrderedDict[str, CacheEntry] = OrderedDict()
self.max_size = max_size
self.default_ttl = default_ttl
self.hits = 0
self.misses = 0
def _生成缓存键(self, messages: list, model: str, provider: str) -> str:
"""基于对话内容和模型生成唯一缓存键"""
content = json.dumps({"messages": messages, "model": model, "provider": provider}, sort_keys=True)
return hashlib.sha256(content.encode()).hexdigest()[:32]
async def 获取缓存(self, messages: list, model: str, provider: str) -> Optional[str]:
"""异步获取缓存的响应"""
key = self._生成缓存键(messages, model, provider)
if key in self.cache:
entry = self.cache[key]
# 检查 TTL 是否过期
if time.time() - entry.timestamp < entry.ttl:
# 移到末尾(LRU 更新)
self.cache.move_to_end(key)
self.hits += 1
return entry.response
else:
# TTL 过期,删除该条目
del self.cache[key]
self.misses += 1
return None
async def 设置缓存(
self,
messages: list,
model: str,
provider: str,
response: str,
token_count: int = 0,
ttl: Optional[int] = None
):
"""设置缓存,异步执行避免阻塞主流程"""
key = self._生成缓存键(messages, model, provider)
# LRU 淘汰:当缓存满时移除最旧的条目
if len(self.cache) >= self.max_size and key not in self.cache:
self.cache.popitem(last=False)
self.cache[key] = CacheEntry(
response=response,
timestamp=time.time(),
ttl=ttl or self.default_ttl,
model=model,
provider=provider,
token_count=token_count
)
def 获取命中率(self) -> float:
"""计算缓存命中率"""
total = self.hits + self.misses
return (self.hits / total * 100) if total > 0 else 0.0
def 获取统计信息(self) -> Dict[str, Any]:
"""获取缓存统计信息"""
return {
"当前条目数": len(self.cache),
"最大容量": self.max_size,
"命中率": f"{self.get_hit_rate():.2f}%",
"命中次数": self.hits,
"未命中次数": self.misses
}
全局缓存实例,建议作为单例管理
响应缓存 = LRU响应缓存(max_size=10000, default_ttl=1800)
这段缓存实现有以下几个关键设计要点:
- LRU 淘汰策略:使用 OrderedDict 保证最近访问的条目优先保留,避免冷数据占用过多内存
- TTL 机制:每条缓存都有独立的过期时间,FAQ 类内容可设置24小时,实时对话设置30分钟
- 异步设计:缓存读写都是 async 方法,配合 asyncio 使用时不阻塞主线程
- 缓存键设计:使用 SHA256 哈希保证键的唯一性,同时支持不同供应商和模型的隔离
第二层:智能多路复用路由
这是架构的核心部分。当主供应商响应超时或返回错误时,系统需要自动、透明地切换到备用供应商,整个过程对上层应用完全不可见。
"""
AI 高可用架构 - 智能路由层实现
支持 HolySheep AI + 多备用供应商的自动故障切换
"""
import asyncio
import logging
from enum import Enum
from typing import Optional, Callable, Awaitable
from dataclasses import dataclass
from datetime import datetime, timedelta
import random
import httpx
logger = logging.getLogger(__name__)
class 供应商状态(Enum):
"""供应商健康状态枚举"""
健康 = "healthy"
降级 = "degraded"
不可用 = "unavailable"
维护中 = "maintenance"
@dataclass
class 供应商配置:
"""供应商配置结构"""
name: str
base_url: str # 例如: https://api.holysheep.ai/v1
api_key: str # 例如: YOUR_HOLYSHEEP_API_KEY
timeout: float = 30.0 # 超时时间(秒)
max_rpm: int = 1000 # 每分钟最大请求数
priority: int = 1 # 优先级,数字越小优先级越高
health_check_interval: int = 60 # 健康检查间隔(秒)
failure_threshold: int = 3 # 连续失败次数阈值,触发熔断
class 健康检查器:
"""供应商健康检查器,异步 Ping 检测"""
def __init__(self, 供应商: 供应商配置):
self.供应商 = 供应商
self.连续失败次数 = 0
self.最后健康时间: Optional[datetime] = None
self.平均响应延迟 = 0.0
self._running = False
async def 执行健康检查(self) -> bool:
"""执行单次健康检查,返回 True 表示健康"""
try:
async with httpx.AsyncClient(timeout=5.0) as client:
start_time = asyncio.get_event_loop().time()
# HolySheep AI 健康检查端点
response = await client.get(
f"{self.供应商.base_url}/models",
headers={
"Authorization": f"Bearer {self.供应商.api_key}",
"Content-Type": "application/json"
}
)
latency = (asyncio.get_event_loop().time() - start_time) * 1000
self.平均响应延迟 = (self.平均响应延迟 * 0.7) + (latency * 0.3)
if response.status_code == 200:
self.连续失败次数 = 0
self.最后健康时间 = datetime.now()
return True
else:
self.连续失败次数 += 1
logger.warning(f"{self.供应商.name} 健康检查失败,状态码: {response.status_code}")
return False
except Exception as e:
self.连续失败次数 += 1
logger.error(f"{self.供应商.name} 健康检查异常: {str(e)}")
return False
def 应该熔断(self) -> bool:
"""判断是否应该触发熔断"""
return self.连续失败次数 >= self.供应商.failure_threshold
def 获取状态(self) -> 供应商状态:
"""获取当前供应商状态"""
if self.应该熔断():
return 供应商状态.不可用
elif self.连续失败次数 > 0:
return 供应商状态.降级
elif self.最后健康时间 and (datetime.now() - self.最后健康时间).seconds > 300:
return 供应商状态.维护中
return 供应商状态.健康
class 智能路由:
"""智能路由引擎,支持多供应商故障自动切换"""
def __init__(self):
self.供应商列表: list[供应商配置] = []
self.健康检查器_map: dict[str, 健康检查器] = {}
self.当前供应商_index = 0
self._lock = asyncio.Lock()
def 添加供应商(self, 供应商: 供应商配置):
"""注册供应商,按优先级排序"""
self.供应商列表.append(供应商)
self.供应商列表.sort(key=lambda x: x.priority)
self.健康检查器_map[供应商.name] = 健康检查器(供应商)
logger.info(f"已注册供应商: {供应商.name}, 优先级: {供应商.priority}, 基础URL: {供应商.base_url}")
async def 启动健康检查循环(self):
"""启动后台健康检查协程"""
async def 检查循环():
while True:
tasks = [
检查器.执行健康检查()
for 检查器 in self.健康检查器_map.values()
]
await asyncio.gather(*tasks, return_exceptions=True)
await asyncio.sleep(60) # 每60秒检查一次
asyncio.create_task(检查循环())
logger.info("健康检查循环已启动")
async def 获取可用供应商(self) -> Optional[供应商配置]:
"""获取当前可用的最优供应商"""
async with self._lock:
for 供应商 in self.供应商列表:
检查器 = self.健康检查器_map[供应商.name]
if 检查器.获取状态() in [供应商状态.健康, 供应商状态.降级]:
return 供应商
return None # 所有供应商都不可用
async def 执行请求_with_故障切换(
self,
request_func: Callable[[供应商配置], Awaitable[Any]],
max_retries: int = 3
) -> Any:
"""带故障切换的请求执行"""
tried_providers = set()
for attempt in range(max_retries):
供应商 = await self.获取可用供应商()
if not 供应商:
# 所有供应商都不可用,尝试恢复第一个供应商
供应商 = self.供应商列表[0]
logger.critical(f"所有供应商不可用,强制尝试主供应商: {供应商.name}")
if 供应商.name in tried_providers:
continue
tried_providers.add(供应商.name)
try:
logger.info(f"尝试供应商: {供应商.name} (第 {attempt + 1} 次尝试)")
result = await asyncio.wait_for(
request_func(供应商),
timeout=供应商.timeout
)
return result
except asyncio.TimeoutError:
logger.warning(f"{供应商.name} 请求超时")
self.健康检查器_map[供应商.name].连续失败次数 += 1
except httpx.HTTPStatusError as e:
logger.error(f"{供应商.name} 返回错误状态码: {e.response.status_code}")
if e.response.status_code in [401, 403]:
# 认证错误不重试,直接抛异常
raise Exception(f"API 认证失败,请检查 API Key: {e.response.status_code}")
self.健康检查器_map[供应商.name].连续失败次数 += 1
except Exception as e:
logger.error(f"{供应商.name} 请求异常: {str(e)}")
self.健康检查器_map[供应商.name].连续失败次数 += 1
raise Exception(f"所有 {len(tried_providers)} 个供应商均失败,已达到最大重试次数")
使用示例:配置 HolySheep AI 为主供应商
路由引擎 = 智能路由()
主供应商 - HolySheheep AI(国内直连,延迟 <50ms)
路由引擎.添加供应商(供应商配置(
name="HolySheep-主",
base_url="https://api.holysheep.ai/v1",
api_key="YOUR_HOLYSHEEP_API_KEY", # 替换为你的 HolySheheep API Key
timeout=30.0,
max_rpm=3000,
priority=1,
failure_threshold=3
))
备用供应商1
路由引擎.添加供应商(供应商配置(
name="备用-供应商A",
base_url="https://备用供应商A.com/v1",
api_key="YOUR_BACKUP_API_KEY_A",
timeout=25.0,
max_rpm=1000,
priority=2,
failure_threshold=2
))
备用供应商2
路由引擎.添加供应商(供应商配置(
name="备用-供应商B",
base_url="https://备用供应商B.com/v1",
api_key="YOUR_BACKUP_API_KEY_B",
timeout=20.0,
max_rpm=800,
priority=3,
failure_threshold=2
))
这段路由引擎的实现有几个关键特性:
- 优先级队列:供应商按 priority 字段排序,priority=1 的供应商会被优先使用
- 熔断机制:连续失败次数超过阈值(默认3次)后自动熔断,不再尝试该供应商
- 健康检查:后台协程每60秒检查所有供应商的可用性,更新状态
- 自动切换:主供应商不可用时自动切换到备用供应商,整个过程对调用方透明
第三层:实时监控与告警
即使有了前两层防护,我们仍然需要实时了解系统运行状态。监控不是为了防止故障发生,而是为了在故障发生时能够第一时间响应。
"""
AI 高可用架构 - 监控与指标采集
集成 Prometheus 格式指标,便于 Grafana 展示
"""
from prometheus_client import Counter, Histogram, Gauge, generate_latest, CONTENT_TYPE_LATEST
from fastapi import FastAPI, Response
import time
from functools import wraps
from typing import Callable, Any
import asyncio
Prometheus 指标定义
请求计数器 = Counter(
'ai_api_requests_total',
'AI API 请求总数',
['provider', 'model', 'status']
)
响应延迟直方图 = Histogram(
'ai_api_response_duration_seconds',
'AI API 响应延迟分布',
['provider', 'model'],
buckets=[0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 30.0]
)
供应商健康状态 = Gauge(
'ai_provider_health_status',
'供应商健康状态 (1=健康, 0.5=降级, 0=不可用)',
['provider']
)
缓存命中率 = Gauge(
'ai_cache_hit_rate',
'缓存命中率百分比',
[]
)
成本计数器 = Counter(
'ai_api_cost_dollars',
'API 调用成本(美元)',
['provider', 'model']
)
class 监控中间件:
"""FastAPI 监控中间件,自动采集所有 AI API 调用的指标"""
def __init__(self, 路由引擎, 缓存实例):
self.路由引擎 = 路由引擎
self.缓存 = 缓存实例
async def 记录请求(
self,
provider: str,
model: str,
status: str,
duration: float,
tokens_used: int = 0,
cost: float = 0.0
):
"""记录一次 API 请求的完整指标"""
请求计数器.labels(provider=provider, model=model, status=status).inc()
响应延迟直方图.labels(provider=provider, model=model).observe(duration)
if cost > 0:
成本计数器.labels(provider=provider, model=model).inc(cost)
# 更新缓存命中率
缓存命中率.set(self.缓存.获取命中率())
# 更新供应商健康状态
检查器 = self.路由引擎.健康检查器_map.get(provider)
if 检查器:
状态 = 检查器.获取状态()
if 状态 == 供应商状态.健康:
供应商健康状态.labels(provider=provider).set(1.0)
elif 状态 == 供应商状态.降级:
供应商健康状态.labels(provider=provider).set(0.5)
else:
供应商健康状态.labels(provider=provider).set(0.0)
def 创建指标端点(self, app: FastAPI):
"""为 FastAPI 应用创建 /metrics 端点"""
@app.get("/metrics")
async def 获取指标():
return Response(content=generate_latest(), media_type=CONTENT_TYPE_LATEST)
def 包装异步函数(self, func: Callable) -> Callable:
"""装饰器:自动记录异步函数的执行指标"""
@wraps(func)
async def wrapper(*args, **kwargs):
start_time = time.time()
provider = kwargs.get('provider', 'unknown')
model = kwargs.get('model', 'unknown')
status = 'success'
try:
result = await func(*args, **kwargs)
return result
except Exception as e:
status = 'error'
raise
finally:
duration = time.time() - start_time
await self.记录请求(
provider=provider,
model=model,
status=status,
duration=duration
)
return wrapper
告警规则示例(适用于 Prometheus AlertManager)
告警规则 = """
groups:
- name: ai_api_alerts
rules:
# 供应商完全不可用告警
- alert: AIProviderDown
expr: ai_provider_health_status == 0
for: 2m
labels:
severity: critical
annotations:
summary: "AI 供应商 {{ $labels.provider }} 不可用"
description: "供应商 {{ $labels.provider }} 已连续故障超过2分钟,请检查备用供应商状态"
# 响应延迟过高告警
- alert: AIHighLatency
expr: histogram_quantile(0.95, ai_api_response_duration_seconds) > 10
for: 5m
labels:
severity: warning
annotations:
summary: "AI API 响应延迟过高"
description: "P95 延迟已达到 {{ $value }}s,请关注用户体验"
# 成本异常告警
- alert: AIHighCost
expr: increase(ai_api_cost_dollars[1h]) > 100
for: 5m
labels:
severity: warning
annotations:
summary: "AI API 调用成本异常"
description: "过去1小时成本已达 ${{ $value }},请确认是否存在异常调用"
"""
通过 Prometheus + Grafana 的组合,你可以实时看到:
- 每个供应商的请求量、成功率和平均延迟
- 缓存命中率的实时变化
- 各供应商的健康状态仪表盘
- API 调用成本的实时统计
完整集成示例:FastAPI + HolySheheep AI
将以上三个层次整合起来,形成一个完整的高可用 AI 代理服务:
"""
完整的 AI 高可用代理服务示例
基于 FastAPI + HolySheheep AI 构建
支持多供应商自动故障切换
"""
import asyncio