凌晨两点,我的生产环境监控系统突然告警。客服反馈大量用户反映 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)

这段缓存实现有以下几个关键设计要点:

第二层:智能多路复用路由

这是架构的核心部分。当主供应商响应超时或返回错误时,系统需要自动、透明地切换到备用供应商,整个过程对上层应用完全不可见。

"""
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 ))

这段路由引擎的实现有几个关键特性:

第三层:实时监控与告警

即使有了前两层防护,我们仍然需要实时了解系统运行状态。监控不是为了防止故障发生,而是为了在故障发生时能够第一时间响应。

"""
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 的组合,你可以实时看到:

完整集成示例:FastAPI + HolySheheep AI

将以上三个层次整合起来,形成一个完整的高可用 AI 代理服务:

"""
完整的 AI 高可用代理服务示例
基于 FastAPI + HolySheheep AI 构建
支持多供应商自动故障切换
"""
import asyncio