使用 FastAPI 构建弹性 AI 架构
Source: Dev.to

随着 AI 驱动的应用从实验性原型转向关键任务的生产服务,弹性、可扩展性和容错性变得至关重要。现代 AI 系统——尤其是使用 Azure OpenAI 等大型语言模型(LLM)的系统——必须能够应对网络不稳定、配额限制、区域性故障以及动态的使用模式。
本文提供了一套实用指南,帮助你构建弹性的 AI 服务,涉及以下技术:
- Python FastAPI 微服务
- Redis 缓存(通过 AWS ElastiCache)
- Azure OpenAI Provisioned Throughput Units (PTUs)
- 高级重试逻辑与灾难恢复策略
- 通过 AWS Secrets Manager 实现安全的配置管理
为什么在 AI 中弹性是不可协商的
AI 服务,尤其是依赖 LLM API 的服务,面临独特的运营挑战:
| 挑战 | 影响 |
|---|---|
| 速率和配额限制 | API 提供商施加令牌/请求上限;需要智能处理。 |
| 瞬时故障 | 网络中断或服务器错误导致间歇性请求失败。 |
| 延迟敏感性 | 用户期望近实时响应;性能至关重要。 |
| 区域性故障 | 云服务中断可能影响整个地理区域。 |
Source: …
架构概览
一个异步的 FastAPI 微服务是系统的核心。它与 Azure OpenAI PTU 进行 LLM 推理通信,并使用 Redis 实现低延迟响应缓存。敏感凭证和重试配置存储在 AWS Secrets Manager 中,而多区域故障转移则通过 Route 53 DNS 地理路由和健康检查来编排。
这种分层设计同时解决了性能和容错问题:
- Redis 减少不必要的 API 调用。
- 重试逻辑 平滑间歇性的网络故障。
- 多区域部署 确保在大规模故障期间的连续性。

_Architecture of an Enterprise-Grade AI_
我们的架构利用关键组件来确保稳健性:

Source: …
深入了解关键弹性使能因素
使用 FastAPI 为 API 加速
FastAPI 是一个异步的 Python Web 框架,提供高并发和快速响应时间——非常适合 AI 后端微服务。
from fastapi import FastAPI
app = FastAPI()
@app.get("/health")
async def health_check():
return {"status": "healthy"}
这个简单的健康检查端点是实现高可用路由策略(例如 AWS Route 53 提供的策略)的关键。
配置层:安全且动态的设置
在代码中嵌入凭证或重试参数会带来安全风险和运维僵化。相反,这种架构在启动时从 AWS Secrets Manager 拉取密钥(如 API 密钥、重试策略),并使用 Python 的 @lru_cache 装饰器将其缓存到内存中。
import boto3
import json
from functools import lru_cache
@lru_cache()
def get_secrets(secret_name: str = "prod/llm-config") -> dict:
client = boto3.client("secretsmanager")
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response["SecretString"])
动态的密钥获取使得可以在不重新部署服务的情况下更新设置——例如重试策略或 API 密钥。
弹性层:智能重试与故障转移
分布式系统中的故障是不可避免的,目标是优雅地处理它们。我们的弹性策略基于三个核心概念:
1. 多 PTU 端点的冗余
来自 Azure OpenAI 的 Provisioned Throughput Unit (PTU) 能保证处理容量,但单个 PTU 可能成为瓶颈或在区域性故障时失效。为此,我们在不同的 Azure 区域(例如 East US、West Europe)部署多个 PTU。应用将这些 PTU 端点视为一个池;如果对某个端点的请求失败,系统会自动切换到下一个端点进行重试,从而实现负载均衡和区域冗余。
2. 带抖动的指数退避
当出现瞬时错误时,立即重试可能加剧问题(即“重试风暴”)。我们实现 带抖动的指数退避:
import random
import asyncio
async def retry_with_backoff(
coro,
max_attempts: int = 5,
base_delay: float = 0.5,
jitter: float = 0.1,
):
for attempt in range(1, max_attempts + 1):
try:
return await coro()
except Exception:
if attempt == max_attempts:
raise
delay = base_delay * (2 ** (attempt - 1))
delay += random.uniform(-jitter, jitter) * delay
await asyncio.sleep(delay)
- 指数增长(
base_delay * 2^(attempt‑1))让重试间隔逐渐拉大。 - 抖动(
± jitter * delay)防止大量客户端同步重试。
3. 熔断器模式
为避免在长时间故障期间对下游服务造成压垮,我们使用 熔断器。当错误阈值超过配置值时,熔断器打开,在冷却期间短路后续调用。
from pybreaker import CircuitBreaker
llm_breaker = CircuitBreaker(
fail_max=5, # 最大连续失败次数
reset_timeout=30, # 重新尝试前的冷却秒数
)
@llm_breaker
async def call_llm(payload):
# 调用 Azure OpenAI PTU 端点
...
当熔断器打开时,服务可以返回缓存的响应或优雅降级的提示信息,从而保持用户体验。
灾难恢复与可观测性
- Multi‑region deployment: 在至少两个 Azure 区域部署 FastAPI 实例和 Redis 集群。使用 Route 53 健康检查将 DNS 故障转移到健康的区域。
- Backup & Restore: 为 Redis(ElastiCache)启用自动快照,并导出 Secrets Manager 的版本。
- Monitoring: 利用 Prometheus + Grafana 监控延迟、错误率和重试指标。导出自定义指标(例如,断路器状态)以帮助进行根因分析。
- Logging: 使用 AWS CloudWatch 或 ELK 堆栈集中日志;包含关联 ID 以在服务之间追踪请求。
综合示例 – 请求流程
- Client → FastAPI: 请求命中最近的 FastAPI 实例(由 DNS 决定)。
- FastAPI → Redis: 检查缓存中是否有最近的响应。
- Cache hit → 返回缓存结果。
- Cache miss → 继续执行第 3 步。
- FastAPI → Azure PTU Pool: 使用
retry_with_backoff+ circuit breaker 调用可用的 PTU 接口。 - Response → Redis: 将新结果存入缓存并设置 TTL(例如 5 分钟)。
- FastAPI → Client: 返回响应。
可观测性
你无法修复看不见的问题。对每次尝试使用结构化日志记录以下内容:
- 使用的端点
- 失败原因
- 应用的延迟
- 最终结果
这些日志会输入监控仪表盘(例如 Grafana),并在失败率或令牌使用量超过预设阈值时触发自动警报。
可伸缩层:使用 Kubernetes 的弹性伸缩
为应对需求波动,我们在 Kubernetes 上部署 FastAPI 服务,并使用 水平 Pod 自动伸缩器 (HPA)。HPA 会根据 CPU 利用率等指标自动增加或减少服务 Pod 的数量。
示例 HPA 策略
| 设置 | 值 |
|---|---|
| 目标 CPU 利用率 | 60 % |
| 最小副本数 | 2 |
| 最大副本数 | 20 |
这确保在流量激增或区域故障切换事件期间,我们的服务能够即时扩容以满足增加的负载,保持性能而无需人工干预。
关键要点
构建企业级 AI 服务意味着从一开始就要把弹性放在首位。这不是事后考虑的,而是核心的架构需求。
- 为故障而设计 – 假设网络、API,甚至整个云区域都会出现故障。构建机制以优雅地处理这些事件。
- 解耦并集中配置 – 使用 AWS Secrets Manager 等服务在外部管理设置。这可以提升安全性和运营敏捷性。
- 实现智能重试 – 结合多个冗余端点、指数退避和抖动,以克服瞬时问题,同时避免对依赖服务造成过大压力。
- 自动化扩展和故障转移 – 利用 Kubernetes HPA 和 AWS Route 53 等工具,创建能够自我修复和自适应的系统,无需人工干预。
通过结合这些实践,您可以构建出不仅功能强大的 AI 服务,还能提供用户期望的稳定性和可靠性。
结论
大规模运行的 AI 系统必须在设计上具备弹性。通过结合异步 API、安全配置、智能重试、跨区域故障转移和自动扩缩容,您可以提供在不利条件下仍保持稳定、高性能和透明的 AI 服务。
关键洞见: 弹性不是一种优化,而是生产 AI 系统的基本需求。
